Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
4c9f3e799b | |||
e645db1630 | |||
d5cf2478d8 | |||
cf34a285b4 | |||
a75083d916 | |||
919ff5e464 | |||
00863b94e8 |
@ -255,8 +255,9 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
List.from(post.categories.map((ele) => ele.alias), growable: true);
|
List.from(post.categories.map((ele) => ele.alias), growable: true);
|
||||||
attachments.addAll(
|
attachments.addAll(
|
||||||
post.body['attachments']
|
post.body['attachments']
|
||||||
?.where((ele) => SnAttachment.fromJson(ele))
|
?.map((ele) => SnAttachment.fromJson(ele))
|
||||||
?.map(PostWriteMedia) ??
|
?.map((ele) => PostWriteMedia(ele))
|
||||||
|
?.cast<PostWriteMedia>() ??
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
poll = post.poll;
|
poll = post.poll;
|
||||||
|
@ -249,8 +249,11 @@ class SnNetworkProvider {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getAttachmentUrl(String ky) {
|
String getAttachmentUrl(String ky, {bool preview = true}) {
|
||||||
if (ky.startsWith("http")) return ky;
|
if (ky.startsWith("http")) return ky;
|
||||||
|
if (!preview) {
|
||||||
|
return '${client.options.baseUrl}/cgi/uc/attachments/$ky?preview=false';
|
||||||
|
}
|
||||||
return '${client.options.baseUrl}/cgi/uc/attachments/$ky';
|
return '${client.options.baseUrl}/cgi/uc/attachments/$ky';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import 'package:surface/providers/experience.dart';
|
|||||||
import 'package:surface/providers/relationship.dart';
|
import 'package:surface/providers/relationship.dart';
|
||||||
import 'package:surface/providers/sn_network.dart';
|
import 'package:surface/providers/sn_network.dart';
|
||||||
import 'package:surface/screens/abuse_report.dart';
|
import 'package:surface/screens/abuse_report.dart';
|
||||||
|
import 'package:surface/screens/account/punishments.dart';
|
||||||
import 'package:surface/types/account.dart';
|
import 'package:surface/types/account.dart';
|
||||||
import 'package:surface/types/check_in.dart';
|
import 'package:surface/types/check_in.dart';
|
||||||
import 'package:surface/types/post.dart';
|
import 'package:surface/types/post.dart';
|
||||||
@ -457,7 +458,7 @@ class _UserScreenState extends State<UserScreen>
|
|||||||
],
|
],
|
||||||
).padding(right: 8),
|
).padding(right: 8),
|
||||||
if (_account!.profile!.description.isNotEmpty)
|
if (_account!.profile!.description.isNotEmpty)
|
||||||
const Gap(12)
|
const Gap(4)
|
||||||
else
|
else
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
if (_account!.profile!.description.isNotEmpty)
|
if (_account!.profile!.description.isNotEmpty)
|
||||||
@ -503,14 +504,15 @@ class _UserScreenState extends State<UserScreen>
|
|||||||
],
|
],
|
||||||
).padding(vertical: 8, horizontal: 12),
|
).padding(vertical: 8, horizontal: 12),
|
||||||
),
|
),
|
||||||
const Gap(8),
|
if (_account!.badges.isNotEmpty) const Gap(8),
|
||||||
Wrap(
|
if (_account!.badges.isNotEmpty)
|
||||||
spacing: 4,
|
Wrap(
|
||||||
runSpacing: 4,
|
spacing: 4,
|
||||||
children: _account!.badges
|
runSpacing: 4,
|
||||||
.map((ele) => AccountBadge(badge: ele))
|
children: _account!.badges
|
||||||
.toList(),
|
.map((ele) => AccountBadge(badge: ele))
|
||||||
).padding(horizontal: 8),
|
.toList(),
|
||||||
|
).padding(horizontal: 8),
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
@ -619,6 +621,17 @@ class _UserScreenState extends State<UserScreen>
|
|||||||
],
|
],
|
||||||
).padding(all: 16),
|
).padding(all: 16),
|
||||||
),
|
),
|
||||||
|
if (_account?.punishments.isNotEmpty ?? false)
|
||||||
|
SliverToBoxAdapter(child: const Divider()),
|
||||||
|
if (_account?.punishments.isNotEmpty ?? false)
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
for (final ele in _account!.punishments)
|
||||||
|
PunishmentInfoCard(ele: ele),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
if (_account?.profile?.links.isNotEmpty ?? false)
|
if (_account?.profile?.links.isNotEmpty ?? false)
|
||||||
SliverToBoxAdapter(child: const Divider()),
|
SliverToBoxAdapter(child: const Divider()),
|
||||||
if (_account?.profile?.links.isNotEmpty ?? false)
|
if (_account?.profile?.links.isNotEmpty ?? false)
|
||||||
|
@ -107,74 +107,7 @@ class _PunishmentsScreenState extends State<PunishmentsScreen> {
|
|||||||
itemCount: _punishments?.length ?? 0,
|
itemCount: _punishments?.length ?? 0,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final ele = _punishments![index];
|
final ele = _punishments![index];
|
||||||
return Card(
|
return PunishmentInfoCard(ele: ele);
|
||||||
margin: EdgeInsets.symmetric(horizontal: 8),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Icon(kPunishmentIcons[ele.type], size: 20),
|
|
||||||
const Gap(6),
|
|
||||||
Expanded(
|
|
||||||
child: Text('punishmentType${ele.type}')
|
|
||||||
.tr()
|
|
||||||
.fontSize(16)
|
|
||||||
.bold(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Text(ele.reason),
|
|
||||||
const Gap(4),
|
|
||||||
Text(
|
|
||||||
'punishmentCreatedAt'.tr(args: [
|
|
||||||
DateFormat().format(
|
|
||||||
ele.createdAt.toLocal(),
|
|
||||||
)
|
|
||||||
]),
|
|
||||||
).opacity(0.8),
|
|
||||||
Text(
|
|
||||||
ele.expiredAt == null
|
|
||||||
? 'punishmentExpiredNever'.tr()
|
|
||||||
: 'punishmentExpiredAt'.tr(args: [
|
|
||||||
DateFormat().format(
|
|
||||||
ele.expiredAt!.toLocal(),
|
|
||||||
)
|
|
||||||
]),
|
|
||||||
).opacity(0.8),
|
|
||||||
const Gap(8),
|
|
||||||
if (ele.moderator != null)
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text('punishmentModerator').tr().opacity(0.75),
|
|
||||||
InkWell(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
AccountImage(
|
|
||||||
content: ele.moderator!.avatar,
|
|
||||||
radius: 8,
|
|
||||||
),
|
|
||||||
const Gap(4),
|
|
||||||
Text(ele.moderator?.nick ?? 'unknown'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
GoRouter.of(context).pushNamed(
|
|
||||||
'accountProfilePage',
|
|
||||||
pathParameters: {
|
|
||||||
'name': ele.moderator!.name,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
else
|
|
||||||
Text('punishmentMadeBySystem').tr().opacity(0.75),
|
|
||||||
],
|
|
||||||
).padding(horizontal: 24, vertical: 16),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
separatorBuilder: (_, __) => const Gap(8),
|
separatorBuilder: (_, __) => const Gap(8),
|
||||||
),
|
),
|
||||||
@ -185,3 +118,82 @@ class _PunishmentsScreenState extends State<PunishmentsScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PunishmentInfoCard extends StatelessWidget {
|
||||||
|
const PunishmentInfoCard({
|
||||||
|
super.key,
|
||||||
|
required this.ele,
|
||||||
|
});
|
||||||
|
|
||||||
|
final SnPunishment ele;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 8),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(kPunishmentIcons[ele.type], size: 20),
|
||||||
|
const Gap(6),
|
||||||
|
Expanded(
|
||||||
|
child:
|
||||||
|
Text('punishmentType${ele.type}').tr().fontSize(16).bold(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Text(ele.reason),
|
||||||
|
const Gap(4),
|
||||||
|
Text(
|
||||||
|
'punishmentCreatedAt'.tr(args: [
|
||||||
|
DateFormat().format(
|
||||||
|
ele.createdAt.toLocal(),
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
).opacity(0.8),
|
||||||
|
Text(
|
||||||
|
ele.expiredAt == null
|
||||||
|
? 'punishmentExpiredNever'.tr()
|
||||||
|
: 'punishmentExpiredAt'.tr(args: [
|
||||||
|
DateFormat().format(
|
||||||
|
ele.expiredAt!.toLocal(),
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
).opacity(0.8),
|
||||||
|
const Gap(8),
|
||||||
|
if (ele.moderator != null)
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('punishmentModerator').tr().opacity(0.75),
|
||||||
|
InkWell(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
AccountImage(
|
||||||
|
content: ele.moderator!.avatar,
|
||||||
|
radius: 8,
|
||||||
|
),
|
||||||
|
const Gap(4),
|
||||||
|
Text(ele.moderator?.nick ?? 'unknown'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
GoRouter.of(context).pushNamed(
|
||||||
|
'accountProfilePage',
|
||||||
|
pathParameters: {
|
||||||
|
'name': ele.moderator!.name,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
else
|
||||||
|
Text('punishmentMadeBySystem').tr().opacity(0.75),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 24, vertical: 16),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -171,7 +171,18 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _onTapChannel(SnChannel channel) {
|
void _onTapChannel(SnChannel channel) {
|
||||||
setState(() => _unreadCounts?[channel.id] = 0);
|
setState(() {
|
||||||
|
_unreadCounts?[channel.id] = 0;
|
||||||
|
if (channel.realmId != null) {
|
||||||
|
_unreadCountsGrouped?[channel.realmId!] =
|
||||||
|
(_unreadCountsGrouped?[channel.realmId!] ?? 0) -
|
||||||
|
(_unreadCounts?[channel.id] ?? 0);
|
||||||
|
}
|
||||||
|
if (channel.type == 1) {
|
||||||
|
_unreadCountsGrouped?[0] =
|
||||||
|
(_unreadCountsGrouped?[0] ?? 0) - (_unreadCounts?[channel.id] ?? 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
if (ResponsiveScaffold.getIsExpand(context)) {
|
if (ResponsiveScaffold.getIsExpand(context)) {
|
||||||
GoRouter.of(context).pushReplacementNamed(
|
GoRouter.of(context).pushReplacementNamed(
|
||||||
'chatRoom',
|
'chatRoom',
|
||||||
@ -180,9 +191,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
'alias': channel.alias,
|
'alias': channel.alias,
|
||||||
},
|
},
|
||||||
).then((value) {
|
).then((value) {
|
||||||
if (mounted) {
|
if (mounted && value == true) {
|
||||||
setState(() => _unreadCounts?[channel.id] = 0);
|
_refreshChannels();
|
||||||
_refreshChannels(noRemote: true);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -193,9 +203,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
'alias': channel.alias,
|
'alias': channel.alias,
|
||||||
},
|
},
|
||||||
).then((value) {
|
).then((value) {
|
||||||
if (mounted) {
|
if (mounted && value == true) {
|
||||||
setState(() => _unreadCounts?[channel.id] = 0);
|
_refreshChannels();
|
||||||
_refreshChannels(noRemote: true);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import 'package:styled_widget/styled_widget.dart';
|
|||||||
import 'package:surface/providers/notification.dart';
|
import 'package:surface/providers/notification.dart';
|
||||||
import 'package:surface/providers/sn_network.dart';
|
import 'package:surface/providers/sn_network.dart';
|
||||||
import 'package:surface/types/notification.dart';
|
import 'package:surface/types/notification.dart';
|
||||||
import 'package:surface/widgets/app_bar_leading.dart';
|
|
||||||
import 'package:surface/widgets/dialog.dart';
|
import 'package:surface/widgets/dialog.dart';
|
||||||
import 'package:surface/widgets/loading_indicator.dart';
|
import 'package:surface/widgets/loading_indicator.dart';
|
||||||
import 'package:surface/widgets/markdown_content.dart';
|
import 'package:surface/widgets/markdown_content.dart';
|
||||||
@ -156,7 +155,7 @@ class _NotificationScreenState extends State<NotificationScreen> {
|
|||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: AutoAppBarLeading(),
|
leading: PageBackButton(),
|
||||||
title: Text('screenNotification').tr(),
|
title: Text('screenNotification').tr(),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
|
@ -22,6 +22,7 @@ abstract class SnAccount with _$SnAccount {
|
|||||||
required String language,
|
required String language,
|
||||||
required SnAccountProfile? profile,
|
required SnAccountProfile? profile,
|
||||||
@Default([]) List<SnAccountBadge> badges,
|
@Default([]) List<SnAccountBadge> badges,
|
||||||
|
@Default([]) List<SnPunishment> punishments,
|
||||||
required DateTime? suspendedAt,
|
required DateTime? suspendedAt,
|
||||||
required int? affiliatedId,
|
required int? affiliatedId,
|
||||||
required int? affiliatedTo,
|
required int? affiliatedTo,
|
||||||
|
@ -29,6 +29,7 @@ mixin _$SnAccount {
|
|||||||
String get language;
|
String get language;
|
||||||
SnAccountProfile? get profile;
|
SnAccountProfile? get profile;
|
||||||
List<SnAccountBadge> get badges;
|
List<SnAccountBadge> get badges;
|
||||||
|
List<SnPunishment> get punishments;
|
||||||
DateTime? get suspendedAt;
|
DateTime? get suspendedAt;
|
||||||
int? get affiliatedId;
|
int? get affiliatedId;
|
||||||
int? get affiliatedTo;
|
int? get affiliatedTo;
|
||||||
@ -69,6 +70,8 @@ mixin _$SnAccount {
|
|||||||
other.language == language) &&
|
other.language == language) &&
|
||||||
(identical(other.profile, profile) || other.profile == profile) &&
|
(identical(other.profile, profile) || other.profile == profile) &&
|
||||||
const DeepCollectionEquality().equals(other.badges, badges) &&
|
const DeepCollectionEquality().equals(other.badges, badges) &&
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other.punishments, punishments) &&
|
||||||
(identical(other.suspendedAt, suspendedAt) ||
|
(identical(other.suspendedAt, suspendedAt) ||
|
||||||
other.suspendedAt == suspendedAt) &&
|
other.suspendedAt == suspendedAt) &&
|
||||||
(identical(other.affiliatedId, affiliatedId) ||
|
(identical(other.affiliatedId, affiliatedId) ||
|
||||||
@ -99,6 +102,7 @@ mixin _$SnAccount {
|
|||||||
language,
|
language,
|
||||||
profile,
|
profile,
|
||||||
const DeepCollectionEquality().hash(badges),
|
const DeepCollectionEquality().hash(badges),
|
||||||
|
const DeepCollectionEquality().hash(punishments),
|
||||||
suspendedAt,
|
suspendedAt,
|
||||||
affiliatedId,
|
affiliatedId,
|
||||||
affiliatedTo,
|
affiliatedTo,
|
||||||
@ -108,7 +112,7 @@ mixin _$SnAccount {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnAccount(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, confirmedAt: $confirmedAt, contacts: $contacts, avatar: $avatar, banner: $banner, name: $name, nick: $nick, permNodes: $permNodes, language: $language, profile: $profile, badges: $badges, suspendedAt: $suspendedAt, affiliatedId: $affiliatedId, affiliatedTo: $affiliatedTo, automatedBy: $automatedBy, automatedId: $automatedId)';
|
return 'SnAccount(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, confirmedAt: $confirmedAt, contacts: $contacts, avatar: $avatar, banner: $banner, name: $name, nick: $nick, permNodes: $permNodes, language: $language, profile: $profile, badges: $badges, punishments: $punishments, suspendedAt: $suspendedAt, affiliatedId: $affiliatedId, affiliatedTo: $affiliatedTo, automatedBy: $automatedBy, automatedId: $automatedId)';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,6 +136,7 @@ abstract mixin class $SnAccountCopyWith<$Res> {
|
|||||||
String language,
|
String language,
|
||||||
SnAccountProfile? profile,
|
SnAccountProfile? profile,
|
||||||
List<SnAccountBadge> badges,
|
List<SnAccountBadge> badges,
|
||||||
|
List<SnPunishment> punishments,
|
||||||
DateTime? suspendedAt,
|
DateTime? suspendedAt,
|
||||||
int? affiliatedId,
|
int? affiliatedId,
|
||||||
int? affiliatedTo,
|
int? affiliatedTo,
|
||||||
@ -167,6 +172,7 @@ class _$SnAccountCopyWithImpl<$Res> implements $SnAccountCopyWith<$Res> {
|
|||||||
Object? language = null,
|
Object? language = null,
|
||||||
Object? profile = freezed,
|
Object? profile = freezed,
|
||||||
Object? badges = null,
|
Object? badges = null,
|
||||||
|
Object? punishments = null,
|
||||||
Object? suspendedAt = freezed,
|
Object? suspendedAt = freezed,
|
||||||
Object? affiliatedId = freezed,
|
Object? affiliatedId = freezed,
|
||||||
Object? affiliatedTo = freezed,
|
Object? affiliatedTo = freezed,
|
||||||
@ -230,6 +236,10 @@ class _$SnAccountCopyWithImpl<$Res> implements $SnAccountCopyWith<$Res> {
|
|||||||
? _self.badges
|
? _self.badges
|
||||||
: badges // ignore: cast_nullable_to_non_nullable
|
: badges // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnAccountBadge>,
|
as List<SnAccountBadge>,
|
||||||
|
punishments: null == punishments
|
||||||
|
? _self.punishments
|
||||||
|
: punishments // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SnPunishment>,
|
||||||
suspendedAt: freezed == suspendedAt
|
suspendedAt: freezed == suspendedAt
|
||||||
? _self.suspendedAt
|
? _self.suspendedAt
|
||||||
: suspendedAt // ignore: cast_nullable_to_non_nullable
|
: suspendedAt // ignore: cast_nullable_to_non_nullable
|
||||||
@ -286,6 +296,7 @@ class _SnAccount extends SnAccount {
|
|||||||
required this.language,
|
required this.language,
|
||||||
required this.profile,
|
required this.profile,
|
||||||
final List<SnAccountBadge> badges = const [],
|
final List<SnAccountBadge> badges = const [],
|
||||||
|
final List<SnPunishment> punishments = const [],
|
||||||
required this.suspendedAt,
|
required this.suspendedAt,
|
||||||
required this.affiliatedId,
|
required this.affiliatedId,
|
||||||
required this.affiliatedTo,
|
required this.affiliatedTo,
|
||||||
@ -294,6 +305,7 @@ class _SnAccount extends SnAccount {
|
|||||||
: _contacts = contacts,
|
: _contacts = contacts,
|
||||||
_permNodes = permNodes,
|
_permNodes = permNodes,
|
||||||
_badges = badges,
|
_badges = badges,
|
||||||
|
_punishments = punishments,
|
||||||
super._();
|
super._();
|
||||||
factory _SnAccount.fromJson(Map<String, dynamic> json) =>
|
factory _SnAccount.fromJson(Map<String, dynamic> json) =>
|
||||||
_$SnAccountFromJson(json);
|
_$SnAccountFromJson(json);
|
||||||
@ -350,6 +362,15 @@ class _SnAccount extends SnAccount {
|
|||||||
return EqualUnmodifiableListView(_badges);
|
return EqualUnmodifiableListView(_badges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<SnPunishment> _punishments;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
List<SnPunishment> get punishments {
|
||||||
|
if (_punishments is EqualUnmodifiableListView) return _punishments;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_punishments);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final DateTime? suspendedAt;
|
final DateTime? suspendedAt;
|
||||||
@override
|
@override
|
||||||
@ -401,6 +422,8 @@ class _SnAccount extends SnAccount {
|
|||||||
other.language == language) &&
|
other.language == language) &&
|
||||||
(identical(other.profile, profile) || other.profile == profile) &&
|
(identical(other.profile, profile) || other.profile == profile) &&
|
||||||
const DeepCollectionEquality().equals(other._badges, _badges) &&
|
const DeepCollectionEquality().equals(other._badges, _badges) &&
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other._punishments, _punishments) &&
|
||||||
(identical(other.suspendedAt, suspendedAt) ||
|
(identical(other.suspendedAt, suspendedAt) ||
|
||||||
other.suspendedAt == suspendedAt) &&
|
other.suspendedAt == suspendedAt) &&
|
||||||
(identical(other.affiliatedId, affiliatedId) ||
|
(identical(other.affiliatedId, affiliatedId) ||
|
||||||
@ -431,6 +454,7 @@ class _SnAccount extends SnAccount {
|
|||||||
language,
|
language,
|
||||||
profile,
|
profile,
|
||||||
const DeepCollectionEquality().hash(_badges),
|
const DeepCollectionEquality().hash(_badges),
|
||||||
|
const DeepCollectionEquality().hash(_punishments),
|
||||||
suspendedAt,
|
suspendedAt,
|
||||||
affiliatedId,
|
affiliatedId,
|
||||||
affiliatedTo,
|
affiliatedTo,
|
||||||
@ -440,7 +464,7 @@ class _SnAccount extends SnAccount {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnAccount(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, confirmedAt: $confirmedAt, contacts: $contacts, avatar: $avatar, banner: $banner, name: $name, nick: $nick, permNodes: $permNodes, language: $language, profile: $profile, badges: $badges, suspendedAt: $suspendedAt, affiliatedId: $affiliatedId, affiliatedTo: $affiliatedTo, automatedBy: $automatedBy, automatedId: $automatedId)';
|
return 'SnAccount(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, confirmedAt: $confirmedAt, contacts: $contacts, avatar: $avatar, banner: $banner, name: $name, nick: $nick, permNodes: $permNodes, language: $language, profile: $profile, badges: $badges, punishments: $punishments, suspendedAt: $suspendedAt, affiliatedId: $affiliatedId, affiliatedTo: $affiliatedTo, automatedBy: $automatedBy, automatedId: $automatedId)';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,6 +491,7 @@ abstract mixin class _$SnAccountCopyWith<$Res>
|
|||||||
String language,
|
String language,
|
||||||
SnAccountProfile? profile,
|
SnAccountProfile? profile,
|
||||||
List<SnAccountBadge> badges,
|
List<SnAccountBadge> badges,
|
||||||
|
List<SnPunishment> punishments,
|
||||||
DateTime? suspendedAt,
|
DateTime? suspendedAt,
|
||||||
int? affiliatedId,
|
int? affiliatedId,
|
||||||
int? affiliatedTo,
|
int? affiliatedTo,
|
||||||
@ -503,6 +528,7 @@ class __$SnAccountCopyWithImpl<$Res> implements _$SnAccountCopyWith<$Res> {
|
|||||||
Object? language = null,
|
Object? language = null,
|
||||||
Object? profile = freezed,
|
Object? profile = freezed,
|
||||||
Object? badges = null,
|
Object? badges = null,
|
||||||
|
Object? punishments = null,
|
||||||
Object? suspendedAt = freezed,
|
Object? suspendedAt = freezed,
|
||||||
Object? affiliatedId = freezed,
|
Object? affiliatedId = freezed,
|
||||||
Object? affiliatedTo = freezed,
|
Object? affiliatedTo = freezed,
|
||||||
@ -566,6 +592,10 @@ class __$SnAccountCopyWithImpl<$Res> implements _$SnAccountCopyWith<$Res> {
|
|||||||
? _self._badges
|
? _self._badges
|
||||||
: badges // ignore: cast_nullable_to_non_nullable
|
: badges // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnAccountBadge>,
|
as List<SnAccountBadge>,
|
||||||
|
punishments: null == punishments
|
||||||
|
? _self._punishments
|
||||||
|
: punishments // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<SnPunishment>,
|
||||||
suspendedAt: freezed == suspendedAt
|
suspendedAt: freezed == suspendedAt
|
||||||
? _self.suspendedAt
|
? _self.suspendedAt
|
||||||
: suspendedAt // ignore: cast_nullable_to_non_nullable
|
: suspendedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
@ -32,6 +32,10 @@ _SnAccount _$SnAccountFromJson(Map<String, dynamic> json) => _SnAccount(
|
|||||||
?.map((e) => SnAccountBadge.fromJson(e as Map<String, dynamic>))
|
?.map((e) => SnAccountBadge.fromJson(e as Map<String, dynamic>))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
const [],
|
const [],
|
||||||
|
punishments: (json['punishments'] as List<dynamic>?)
|
||||||
|
?.map((e) => SnPunishment.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
suspendedAt: json['suspended_at'] == null
|
suspendedAt: json['suspended_at'] == null
|
||||||
? null
|
? null
|
||||||
: DateTime.parse(json['suspended_at'] as String),
|
: DateTime.parse(json['suspended_at'] as String),
|
||||||
@ -57,6 +61,7 @@ Map<String, dynamic> _$SnAccountToJson(_SnAccount instance) =>
|
|||||||
'language': instance.language,
|
'language': instance.language,
|
||||||
'profile': instance.profile?.toJson(),
|
'profile': instance.profile?.toJson(),
|
||||||
'badges': instance.badges.map((e) => e.toJson()).toList(),
|
'badges': instance.badges.map((e) => e.toJson()).toList(),
|
||||||
|
'punishments': instance.punishments.map((e) => e.toJson()).toList(),
|
||||||
'suspended_at': instance.suspendedAt?.toIso8601String(),
|
'suspended_at': instance.suspendedAt?.toIso8601String(),
|
||||||
'affiliated_id': instance.affiliatedId,
|
'affiliated_id': instance.affiliatedId,
|
||||||
'affiliated_to': instance.affiliatedTo,
|
'affiliated_to': instance.affiliatedTo,
|
||||||
|
@ -22,142 +22,151 @@ class AccountPopoverCard extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final sn = context.read<SnNetworkProvider>();
|
final sn = context.read<SnNetworkProvider>();
|
||||||
|
|
||||||
return Column(
|
return SingleChildScrollView(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (data.banner.isNotEmpty)
|
if (data.banner.isNotEmpty)
|
||||||
Container(
|
ClipRRect(
|
||||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
borderRadius: BorderRadius.circular(16),
|
||||||
child: AspectRatio(
|
child: Container(
|
||||||
aspectRatio: 16 / 7,
|
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||||
child: AutoResizeUniversalImage(
|
child: AspectRatio(
|
||||||
sn.getAttachmentUrl(data.banner),
|
aspectRatio: 16 / 7,
|
||||||
fit: BoxFit.cover,
|
child: AutoResizeUniversalImage(
|
||||||
),
|
sn.getAttachmentUrl(data.banner),
|
||||||
),
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
// Top padding
|
|
||||||
Gap(16),
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
AccountImage(
|
|
||||||
content: data.avatar,
|
|
||||||
radius: 20,
|
|
||||||
),
|
|
||||||
Gap(16),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Text(data.nick).bold(),
|
|
||||||
Text('@${data.name}').fontSize(13).opacity(0.75),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.pop(context);
|
|
||||||
GoRouter.of(context).pushNamed(
|
|
||||||
'accountProfilePage',
|
|
||||||
pathParameters: {'name': data.name},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
icon: const Icon(Symbols.chevron_right),
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
visualDensity: const VisualDensity(horizontal: -4, vertical: -4),
|
|
||||||
),
|
|
||||||
const Gap(8)
|
|
||||||
],
|
|
||||||
).padding(horizontal: 16),
|
|
||||||
if (data.badges.isNotEmpty)
|
|
||||||
Wrap(
|
|
||||||
spacing: 4,
|
|
||||||
children: data.badges
|
|
||||||
.map(
|
|
||||||
(ele) => AccountBadge(badge: ele),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
).padding(horizontal: 24, bottom: 12, top: 12),
|
|
||||||
if (data.profile?.description.isNotEmpty ?? false)
|
|
||||||
Text(
|
|
||||||
data.profile?.description ?? '',
|
|
||||||
maxLines: 2,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
).padding(horizontal: 26, bottom: 8),
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
const Icon(Symbols.star),
|
|
||||||
const Gap(8),
|
|
||||||
Text('Lv${getLevelFromExp(data.profile?.experience ?? 0)}'),
|
|
||||||
const Gap(8),
|
|
||||||
Text(calcLevelUpProgressLevel(data.profile?.experience ?? 0))
|
|
||||||
.fontSize(11)
|
|
||||||
.opacity(0.5),
|
|
||||||
const Gap(8),
|
|
||||||
Container(
|
|
||||||
width: double.infinity,
|
|
||||||
constraints: const BoxConstraints(maxWidth: 160),
|
|
||||||
child: LinearProgressIndicator(
|
|
||||||
value: calcLevelUpProgress(data.profile?.experience ?? 0),
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
|
|
||||||
).alignment(Alignment.centerLeft),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
).padding(horizontal: 24),
|
|
||||||
FutureBuilder(
|
|
||||||
future: sn.client.get('/cgi/id/users/${data.name}/status'),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
final SnAccountStatusInfo? status = snapshot.hasData
|
|
||||||
? SnAccountStatusInfo.fromJson(snapshot.data!.data)
|
|
||||||
: null;
|
|
||||||
return Row(
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
(status?.isDisturbable ?? true)
|
|
||||||
? Symbols.circle
|
|
||||||
: Symbols.do_not_disturb_on,
|
|
||||||
fill: (status?.isOnline ?? false) ? 1 : 0,
|
|
||||||
size: 16,
|
|
||||||
color: (status?.isOnline ?? false)
|
|
||||||
? (status?.isDisturbable ?? true)
|
|
||||||
? Colors.green
|
|
||||||
: Colors.red
|
|
||||||
: Colors.grey,
|
|
||||||
).padding(all: 4),
|
|
||||||
const Gap(8),
|
|
||||||
Text(
|
|
||||||
status != null
|
|
||||||
? (status.status?.label.isNotEmpty ?? false)
|
|
||||||
? status.status!.label
|
|
||||||
: status.isOnline
|
|
||||||
? 'accountStatusOnline'.tr()
|
|
||||||
: 'accountStatusOffline'.tr()
|
|
||||||
: 'loading'.tr(),
|
|
||||||
),
|
),
|
||||||
if (status != null &&
|
),
|
||||||
!status.isOnline &&
|
).padding(all: 16)
|
||||||
status.lastSeenAt != null)
|
else
|
||||||
|
const Gap(16),
|
||||||
|
// Top padding
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
AccountImage(
|
||||||
|
content: data.avatar,
|
||||||
|
radius: 20,
|
||||||
|
),
|
||||||
|
Gap(16),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(data.nick).bold(),
|
||||||
|
Text('@${data.name}').fontSize(13).opacity(0.75),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
GoRouter.of(context).pushReplacementNamed(
|
||||||
|
'accountProfilePage',
|
||||||
|
pathParameters: {'name': data.name},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: const Icon(Symbols.chevron_right),
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
visualDensity:
|
||||||
|
const VisualDensity(horizontal: -4, vertical: -4),
|
||||||
|
),
|
||||||
|
const Gap(8)
|
||||||
|
],
|
||||||
|
).padding(horizontal: 16),
|
||||||
|
if (data.badges.isNotEmpty)
|
||||||
|
Wrap(
|
||||||
|
spacing: 4,
|
||||||
|
children: data.badges
|
||||||
|
.map(
|
||||||
|
(ele) => AccountBadge(badge: ele),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
).padding(horizontal: 24, bottom: 12, top: 12),
|
||||||
|
if (data.profile?.description.isNotEmpty ?? false)
|
||||||
|
Text(
|
||||||
|
data.profile?.description ?? '',
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
).padding(horizontal: 26, bottom: 8)
|
||||||
|
else
|
||||||
|
const Gap(12),
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.star),
|
||||||
|
const Gap(8),
|
||||||
|
Text('Lv${getLevelFromExp(data.profile?.experience ?? 0)}'),
|
||||||
|
const Gap(8),
|
||||||
|
Text(calcLevelUpProgressLevel(data.profile?.experience ?? 0))
|
||||||
|
.fontSize(11)
|
||||||
|
.opacity(0.5),
|
||||||
|
const Gap(8),
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
constraints: const BoxConstraints(maxWidth: 160),
|
||||||
|
child: LinearProgressIndicator(
|
||||||
|
value: calcLevelUpProgress(data.profile?.experience ?? 0),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.surfaceContainer,
|
||||||
|
).alignment(Alignment.centerLeft),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 24),
|
||||||
|
FutureBuilder(
|
||||||
|
future: sn.client.get('/cgi/id/users/${data.name}/status'),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final SnAccountStatusInfo? status = snapshot.hasData
|
||||||
|
? SnAccountStatusInfo.fromJson(snapshot.data!.data)
|
||||||
|
: null;
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
(status?.isDisturbable ?? true)
|
||||||
|
? Symbols.circle
|
||||||
|
: Symbols.do_not_disturb_on,
|
||||||
|
fill: (status?.isOnline ?? false) ? 1 : 0,
|
||||||
|
size: 16,
|
||||||
|
color: (status?.isOnline ?? false)
|
||||||
|
? (status?.isDisturbable ?? true)
|
||||||
|
? Colors.green
|
||||||
|
: Colors.red
|
||||||
|
: Colors.grey,
|
||||||
|
).padding(all: 4),
|
||||||
|
const Gap(8),
|
||||||
Text(
|
Text(
|
||||||
'accountStatusLastSeen'.tr(args: [
|
status != null
|
||||||
status.lastSeenAt != null
|
? (status.status?.label.isNotEmpty ?? false)
|
||||||
? RelativeTime(context).format(
|
? status.status!.label
|
||||||
status.lastSeenAt!.toLocal(),
|
: status.isOnline
|
||||||
)
|
? 'accountStatusOnline'.tr()
|
||||||
: 'unknown',
|
: 'accountStatusOffline'.tr()
|
||||||
]),
|
: 'loading'.tr(),
|
||||||
).padding(left: 6).opacity(0.75),
|
),
|
||||||
],
|
if (status != null &&
|
||||||
).padding(horizontal: 24);
|
!status.isOnline &&
|
||||||
},
|
status.lastSeenAt != null)
|
||||||
),
|
Text(
|
||||||
// Bottom padding
|
'accountStatusLastSeen'.tr(args: [
|
||||||
const Gap(16),
|
status.lastSeenAt != null
|
||||||
],
|
? RelativeTime(context).format(
|
||||||
|
status.lastSeenAt!.toLocal(),
|
||||||
|
)
|
||||||
|
: 'unknown',
|
||||||
|
]),
|
||||||
|
).padding(left: 6).opacity(0.75),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 24);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
// Bottom padding
|
||||||
|
const Gap(64),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ class AttachmentItem extends StatelessWidget {
|
|||||||
final String? heroTag;
|
final String? heroTag;
|
||||||
final BoxFit fit;
|
final BoxFit fit;
|
||||||
final FilterQuality? filterQuality;
|
final FilterQuality? filterQuality;
|
||||||
|
final Function? onZoom;
|
||||||
|
|
||||||
const AttachmentItem({
|
const AttachmentItem({
|
||||||
super.key,
|
super.key,
|
||||||
@ -32,6 +33,7 @@ class AttachmentItem extends StatelessWidget {
|
|||||||
required this.data,
|
required this.data,
|
||||||
required this.heroTag,
|
required this.heroTag,
|
||||||
this.filterQuality,
|
this.filterQuality,
|
||||||
|
this.onZoom,
|
||||||
});
|
});
|
||||||
|
|
||||||
Widget _buildContent(BuildContext context) {
|
Widget _buildContent(BuildContext context) {
|
||||||
@ -94,7 +96,14 @@ class AttachmentItem extends StatelessWidget {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return _buildContent(context);
|
return GestureDetector(
|
||||||
|
child: _buildContent(context),
|
||||||
|
onTap: () {
|
||||||
|
if (data?.mimetype.startsWith('image') ?? false) {
|
||||||
|
onZoom?.call();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,40 +74,35 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
return Container(
|
return Container(
|
||||||
padding: widget.padding ?? EdgeInsets.zero,
|
padding: widget.padding ?? EdgeInsets.zero,
|
||||||
constraints: constraints,
|
constraints: constraints,
|
||||||
child: GestureDetector(
|
child: AspectRatio(
|
||||||
child: AspectRatio(
|
aspectRatio: singleAspectRatio,
|
||||||
aspectRatio: singleAspectRatio,
|
child: Container(
|
||||||
child: Container(
|
decoration: BoxDecoration(
|
||||||
decoration: BoxDecoration(
|
color: backgroundColor,
|
||||||
color: backgroundColor,
|
border: Border.fromBorderSide(borderSide),
|
||||||
border: Border.fromBorderSide(borderSide),
|
borderRadius: AttachmentList.kDefaultRadius,
|
||||||
borderRadius: AttachmentList.kDefaultRadius,
|
),
|
||||||
),
|
child: ClipRRect(
|
||||||
child: ClipRRect(
|
borderRadius: AttachmentList.kDefaultRadius,
|
||||||
borderRadius: AttachmentList.kDefaultRadius,
|
child: AttachmentItem(
|
||||||
child: AttachmentItem(
|
data: widget.data[0],
|
||||||
data: widget.data[0],
|
heroTag: heroTags[0],
|
||||||
heroTag: heroTags[0],
|
fit: widget.fit,
|
||||||
fit: widget.fit,
|
filterQuality: widget.filterQuality,
|
||||||
filterQuality: widget.filterQuality,
|
onZoom: () {
|
||||||
),
|
context.pushTransparentRoute(
|
||||||
|
AttachmentZoomView(
|
||||||
|
data: widget.data.where((ele) => ele != null).cast(),
|
||||||
|
initialIndex: 0,
|
||||||
|
heroTags: heroTags,
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.black.withOpacity(0.7),
|
||||||
|
rootNavigator: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () {
|
|
||||||
if (widget.data.firstOrNull?.mediaType != SnMediaType.image) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
context.pushTransparentRoute(
|
|
||||||
AttachmentZoomView(
|
|
||||||
data: widget.data.where((ele) => ele != null).cast(),
|
|
||||||
initialIndex: 0,
|
|
||||||
heroTags: heroTags,
|
|
||||||
),
|
|
||||||
backgroundColor: Colors.black.withOpacity(0.7),
|
|
||||||
rootNavigator: true,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -133,33 +128,27 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
mainAxisSpacing: 4,
|
mainAxisSpacing: 4,
|
||||||
children: widget.data
|
children: widget.data
|
||||||
.mapIndexed(
|
.mapIndexed(
|
||||||
(idx, ele) => GestureDetector(
|
(idx, ele) => Container(
|
||||||
child: Container(
|
constraints: constraints,
|
||||||
constraints: constraints,
|
child: AttachmentItem(
|
||||||
child: AttachmentItem(
|
data: ele,
|
||||||
data: ele,
|
heroTag: heroTags[idx],
|
||||||
heroTag: heroTags[idx],
|
fit: BoxFit.cover,
|
||||||
fit: BoxFit.cover,
|
filterQuality: widget.filterQuality,
|
||||||
filterQuality: widget.filterQuality,
|
onZoom: () {
|
||||||
),
|
context.pushTransparentRoute(
|
||||||
|
AttachmentZoomView(
|
||||||
|
data: widget.data
|
||||||
|
.where((ele) => ele != null)
|
||||||
|
.cast(),
|
||||||
|
initialIndex: idx,
|
||||||
|
heroTags: heroTags,
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.black.withOpacity(0.7),
|
||||||
|
rootNavigator: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
onTap: () {
|
|
||||||
if (widget.data[idx]!.mediaType !=
|
|
||||||
SnMediaType.image) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
context.pushTransparentRoute(
|
|
||||||
AttachmentZoomView(
|
|
||||||
data: widget.data
|
|
||||||
.where((ele) => ele != null)
|
|
||||||
.cast(),
|
|
||||||
initialIndex: idx,
|
|
||||||
heroTags: heroTags,
|
|
||||||
),
|
|
||||||
backgroundColor: Colors.black.withOpacity(0.7),
|
|
||||||
rootNavigator: true,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.toList(),
|
.toList(),
|
||||||
@ -181,17 +170,30 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: widget.data
|
children: widget.data
|
||||||
.mapIndexed(
|
.mapIndexed(
|
||||||
(idx, ele) => GestureDetector(
|
(idx, ele) => AspectRatio(
|
||||||
child: AspectRatio(
|
aspectRatio: ele?.data['ratio']?.toDouble() ?? 1,
|
||||||
aspectRatio: ele?.data['ratio']?.toDouble() ?? 1,
|
child: Container(
|
||||||
child: Container(
|
constraints: constraints,
|
||||||
constraints: constraints,
|
child: AttachmentItem(
|
||||||
child: AttachmentItem(
|
data: ele,
|
||||||
data: ele,
|
heroTag: heroTags[idx],
|
||||||
heroTag: heroTags[idx],
|
fit: BoxFit.cover,
|
||||||
fit: BoxFit.cover,
|
filterQuality: widget.filterQuality,
|
||||||
filterQuality: widget.filterQuality,
|
onZoom: () {
|
||||||
),
|
context.pushTransparentRoute(
|
||||||
|
AttachmentZoomView(
|
||||||
|
data: widget.data
|
||||||
|
.where((ele) =>
|
||||||
|
ele != null &&
|
||||||
|
ele.mediaType == SnMediaType.image)
|
||||||
|
.cast(),
|
||||||
|
initialIndex: idx,
|
||||||
|
heroTags: heroTags,
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.black.withOpacity(0.7),
|
||||||
|
rootNavigator: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -222,56 +224,52 @@ class _AttachmentListState extends State<AttachmentList> {
|
|||||||
child: AspectRatio(
|
child: AspectRatio(
|
||||||
aspectRatio:
|
aspectRatio:
|
||||||
(widget.data[idx]?.data['ratio'] ?? 1).toDouble(),
|
(widget.data[idx]?.data['ratio'] ?? 1).toDouble(),
|
||||||
child: GestureDetector(
|
child: Stack(
|
||||||
onTap: () {
|
fit: StackFit.expand,
|
||||||
if (widget.data[idx]?.mediaType !=
|
children: [
|
||||||
SnMediaType.image) {
|
Container(
|
||||||
return;
|
decoration: BoxDecoration(
|
||||||
}
|
color: backgroundColor,
|
||||||
context.pushTransparentRoute(
|
border: Border.all(
|
||||||
AttachmentZoomView(
|
width: 1,
|
||||||
data: widget.data
|
color: Theme.of(context).dividerColor,
|
||||||
.where((ele) =>
|
|
||||||
ele != null &&
|
|
||||||
ele.mediaType == SnMediaType.image)
|
|
||||||
.cast(),
|
|
||||||
initialIndex: idx,
|
|
||||||
heroTags: heroTags,
|
|
||||||
),
|
|
||||||
backgroundColor: Colors.black.withOpacity(0.7),
|
|
||||||
rootNavigator: true,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Stack(
|
|
||||||
fit: StackFit.expand,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: backgroundColor,
|
|
||||||
border: Border.all(
|
|
||||||
width: 1,
|
|
||||||
color: Theme.of(context).dividerColor,
|
|
||||||
),
|
|
||||||
borderRadius: AttachmentList.kDefaultRadius,
|
|
||||||
),
|
),
|
||||||
child: ClipRRect(
|
borderRadius: AttachmentList.kDefaultRadius,
|
||||||
borderRadius: AttachmentList.kDefaultRadius,
|
),
|
||||||
child: AttachmentItem(
|
child: ClipRRect(
|
||||||
data: widget.data[idx],
|
borderRadius: AttachmentList.kDefaultRadius,
|
||||||
heroTag: heroTags[idx],
|
child: AttachmentItem(
|
||||||
filterQuality: widget.filterQuality,
|
data: widget.data[idx],
|
||||||
),
|
heroTag: heroTags[idx],
|
||||||
|
filterQuality: widget.filterQuality,
|
||||||
|
onZoom: () {
|
||||||
|
context.pushTransparentRoute(
|
||||||
|
AttachmentZoomView(
|
||||||
|
data: widget.data
|
||||||
|
.where((ele) =>
|
||||||
|
ele != null &&
|
||||||
|
ele.mediaType ==
|
||||||
|
SnMediaType.image)
|
||||||
|
.cast(),
|
||||||
|
initialIndex: idx,
|
||||||
|
heroTags: heroTags,
|
||||||
|
),
|
||||||
|
backgroundColor:
|
||||||
|
Colors.black.withOpacity(0.7),
|
||||||
|
rootNavigator: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Positioned(
|
),
|
||||||
right: 8,
|
Positioned(
|
||||||
bottom: 8,
|
right: 8,
|
||||||
child: Chip(
|
bottom: 8,
|
||||||
label: Text('${idx + 1}/${widget.data.length}'),
|
child: Chip(
|
||||||
),
|
label: Text('${idx + 1}/${widget.data.length}'),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -64,7 +64,7 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
|
|||||||
Future<void> _saveToAlbum(int idx) async {
|
Future<void> _saveToAlbum(int idx) async {
|
||||||
final sn = context.read<SnNetworkProvider>();
|
final sn = context.read<SnNetworkProvider>();
|
||||||
final item = widget.data.elementAt(idx);
|
final item = widget.data.elementAt(idx);
|
||||||
final url = sn.getAttachmentUrl(item.rid);
|
final url = sn.getAttachmentUrl(item.rid, preview: false);
|
||||||
|
|
||||||
if (kIsWeb || Platform.isLinux) {
|
if (kIsWeb || Platform.isLinux) {
|
||||||
await launchUrlString(url);
|
await launchUrlString(url);
|
||||||
@ -181,7 +181,10 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
|
|||||||
scaleState == PhotoViewScaleState.initial);
|
scaleState == PhotoViewScaleState.initial);
|
||||||
},
|
},
|
||||||
imageProvider: UniversalImage.provider(
|
imageProvider: UniversalImage.provider(
|
||||||
sn.getAttachmentUrl(widget.data.first.rid),
|
sn.getAttachmentUrl(
|
||||||
|
widget.data.first.rid,
|
||||||
|
preview: false,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -199,7 +202,10 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
|
|||||||
widget.heroTags?.elementAt(idx) ?? uuid.v4();
|
widget.heroTags?.elementAt(idx) ?? uuid.v4();
|
||||||
return PhotoViewGalleryPageOptions(
|
return PhotoViewGalleryPageOptions(
|
||||||
imageProvider: UniversalImage.provider(
|
imageProvider: UniversalImage.provider(
|
||||||
sn.getAttachmentUrl(widget.data.elementAt(idx).rid),
|
sn.getAttachmentUrl(
|
||||||
|
widget.data.elementAt(idx).rid,
|
||||||
|
preview: false,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
heroAttributes: PhotoViewHeroAttributes(
|
heroAttributes: PhotoViewHeroAttributes(
|
||||||
tag: 'attachment-${widget.data.first.rid}-$heroTag',
|
tag: 'attachment-${widget.data.first.rid}-$heroTag',
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import 'dart:math' as math;
|
|
||||||
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_context_menu/flutter_context_menu.dart';
|
import 'package:flutter_context_menu/flutter_context_menu.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:popover/popover.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:surface/providers/config.dart';
|
import 'package:surface/providers/config.dart';
|
||||||
@ -120,20 +117,9 @@ class ChatMessage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (user == null) return;
|
if (user == null) return;
|
||||||
showPopover(
|
showModalBottomSheet(
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).colorScheme.surface,
|
|
||||||
context: context,
|
context: context,
|
||||||
transition: PopoverTransition.other,
|
builder: (context) => AccountPopoverCard(data: user),
|
||||||
bodyBuilder: (context) => SizedBox(
|
|
||||||
width: math.min(
|
|
||||||
400, MediaQuery.of(context).size.width - 10),
|
|
||||||
child: AccountPopoverCard(data: user),
|
|
||||||
),
|
|
||||||
direction: PopoverDirection.bottom,
|
|
||||||
arrowHeight: 5,
|
|
||||||
arrowWidth: 15,
|
|
||||||
arrowDxOffset: -190,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -100,6 +100,7 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
|
|||||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
leading: AccountImage(
|
leading: AccountImage(
|
||||||
content: ua.user?.avatar,
|
content: ua.user?.avatar,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
fallbackWidget:
|
fallbackWidget:
|
||||||
ua.isAuthorized ? null : const Icon(Symbols.login),
|
ua.isAuthorized ? null : const Icon(Symbols.login),
|
||||||
),
|
),
|
||||||
@ -122,15 +123,6 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
|
|||||||
Scaffold.of(context).closeDrawer();
|
Scaffold.of(context).closeDrawer();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Symbols.settings, fill: 1),
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
onPressed: () {
|
|
||||||
GoRouter.of(context).pushNamed('settings');
|
|
||||||
Scaffold.of(context).closeDrawer();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
@ -12,7 +12,6 @@ import 'package:go_router/go_router.dart';
|
|||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:popover/popover.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:qr_flutter/qr_flutter.dart';
|
import 'package:qr_flutter/qr_flutter.dart';
|
||||||
import 'package:relative_time/relative_time.dart';
|
import 'package:relative_time/relative_time.dart';
|
||||||
@ -1274,20 +1273,11 @@ class _PostAvatar extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
showPopover(
|
showModalBottomSheet(
|
||||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
|
||||||
context: context,
|
context: context,
|
||||||
transition: PopoverTransition.other,
|
builder: (context) => PublisherPopoverCard(
|
||||||
bodyBuilder: (context) => SizedBox(
|
data: data.publisher,
|
||||||
width: math.min(400, MediaQuery.of(context).size.width - 10),
|
|
||||||
child: PublisherPopoverCard(
|
|
||||||
data: data.publisher,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
direction: PopoverDirection.bottom,
|
|
||||||
arrowHeight: 5,
|
|
||||||
arrowWidth: 15,
|
|
||||||
arrowDxOffset: -190,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -24,125 +24,137 @@ class PublisherPopoverCard extends StatelessWidget {
|
|||||||
|
|
||||||
final user = data.type == 0 ? ud.getFromCache(data.accountId) : null;
|
final user = data.type == 0 ? ud.getFromCache(data.accountId) : null;
|
||||||
|
|
||||||
return Column(
|
return SingleChildScrollView(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (data.banner.isNotEmpty)
|
if (data.banner.isNotEmpty)
|
||||||
Container(
|
ClipRRect(
|
||||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
borderRadius: BorderRadius.circular(16),
|
||||||
child: AspectRatio(
|
child: Container(
|
||||||
aspectRatio: 16 / 7,
|
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||||
child: AutoResizeUniversalImage(
|
child: AspectRatio(
|
||||||
sn.getAttachmentUrl(data.banner),
|
aspectRatio: 16 / 7,
|
||||||
fit: BoxFit.cover,
|
child: AutoResizeUniversalImage(
|
||||||
|
sn.getAttachmentUrl(data.banner),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
).padding(all: 16)
|
||||||
),
|
else
|
||||||
// Top padding
|
// Top padding
|
||||||
Gap(16),
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
AccountImage(
|
|
||||||
content: data.avatar,
|
|
||||||
radius: 20,
|
|
||||||
borderRadius: data.type == 1 ? 8 : 20,
|
|
||||||
),
|
|
||||||
Gap(16),
|
Gap(16),
|
||||||
Expanded(
|
Row(
|
||||||
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
mainAxisSize: MainAxisSize.min,
|
AccountImage(
|
||||||
children: [
|
content: data.avatar,
|
||||||
Text(data.nick).bold(),
|
radius: 20,
|
||||||
Text('@${data.name}').fontSize(13).opacity(0.75),
|
borderRadius: data.type == 1 ? 8 : 20,
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
Gap(16),
|
||||||
IconButton(
|
Expanded(
|
||||||
onPressed: () {
|
child: Column(
|
||||||
Navigator.pop(context);
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
GoRouter.of(context).pushNamed(
|
mainAxisSize: MainAxisSize.min,
|
||||||
'postPublisher',
|
children: [
|
||||||
pathParameters: {'name': data.name},
|
Text(data.nick).bold(),
|
||||||
);
|
Text('@${data.name}').fontSize(13).opacity(0.75),
|
||||||
},
|
],
|
||||||
icon: const Icon(Symbols.chevron_right),
|
),
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
visualDensity: const VisualDensity(horizontal: -4, vertical: -4),
|
|
||||||
),
|
|
||||||
const Gap(8)
|
|
||||||
],
|
|
||||||
).padding(horizontal: 16),
|
|
||||||
if (user != null && user.badges.isNotEmpty)
|
|
||||||
Wrap(
|
|
||||||
spacing: 4,
|
|
||||||
children: user.badges
|
|
||||||
.map(
|
|
||||||
(ele) => AccountBadge(badge: ele),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
).padding(horizontal: 24, top: 16),
|
|
||||||
const Gap(16),
|
|
||||||
if (data.description.isNotEmpty)
|
|
||||||
Text(
|
|
||||||
data.description,
|
|
||||||
maxLines: 2,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
).padding(horizontal: 26, bottom: 20),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Text('publisherSocialPoint').tr().fontSize(13).opacity(0.75),
|
|
||||||
Text((data.totalUpvote - data.totalDownvote).toString()),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
IconButton(
|
||||||
SizedBox(
|
onPressed: () {
|
||||||
height: 20,
|
Navigator.pop(context);
|
||||||
child: const VerticalDivider(
|
GoRouter.of(context).pushNamed(
|
||||||
thickness: 1,
|
'postPublisher',
|
||||||
|
pathParameters: {'name': data.name},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: const Icon(Symbols.chevron_right),
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
visualDensity:
|
||||||
|
const VisualDensity(horizontal: -4, vertical: -4),
|
||||||
),
|
),
|
||||||
).padding(horizontal: 8),
|
const Gap(8)
|
||||||
Expanded(
|
],
|
||||||
child: Column(
|
).padding(horizontal: 16),
|
||||||
mainAxisSize: MainAxisSize.min,
|
if (user != null && user.badges.isNotEmpty)
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
Wrap(
|
||||||
children: [
|
spacing: 4,
|
||||||
Text('publisherTotalUpvote').tr().fontSize(13).opacity(0.75),
|
children: user.badges
|
||||||
Text(data.totalUpvote.toString()),
|
.map(
|
||||||
],
|
(ele) => AccountBadge(badge: ele),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
).padding(horizontal: 24, top: 16),
|
||||||
|
const Gap(16),
|
||||||
|
if (data.description.isNotEmpty)
|
||||||
|
Text(
|
||||||
|
data.description,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
).padding(horizontal: 26, bottom: 20),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text('publisherSocialPoint')
|
||||||
|
.tr()
|
||||||
|
.fontSize(13)
|
||||||
|
.opacity(0.75),
|
||||||
|
Text((data.totalUpvote - data.totalDownvote).toString()),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
SizedBox(
|
||||||
SizedBox(
|
height: 20,
|
||||||
height: 20,
|
child: const VerticalDivider(
|
||||||
child: const VerticalDivider(
|
thickness: 1,
|
||||||
thickness: 1,
|
),
|
||||||
|
).padding(horizontal: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text('publisherTotalUpvote')
|
||||||
|
.tr()
|
||||||
|
.fontSize(13)
|
||||||
|
.opacity(0.75),
|
||||||
|
Text(data.totalUpvote.toString()),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
).padding(horizontal: 8),
|
SizedBox(
|
||||||
Expanded(
|
height: 20,
|
||||||
child: Column(
|
child: const VerticalDivider(
|
||||||
mainAxisSize: MainAxisSize.min,
|
thickness: 1,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
),
|
||||||
children: [
|
).padding(horizontal: 8),
|
||||||
Text('publisherTotalDownvote')
|
Expanded(
|
||||||
.tr()
|
child: Column(
|
||||||
.fontSize(13)
|
mainAxisSize: MainAxisSize.min,
|
||||||
.opacity(0.75),
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
Text(data.totalDownvote.toString()),
|
children: [
|
||||||
],
|
Text('publisherTotalDownvote')
|
||||||
|
.tr()
|
||||||
|
.fontSize(13)
|
||||||
|
.opacity(0.75),
|
||||||
|
Text(data.totalDownvote.toString()),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
).padding(horizontal: 16),
|
||||||
).padding(horizontal: 16),
|
// Bottom padding
|
||||||
// Bottom padding
|
const Gap(64),
|
||||||
const Gap(16),
|
],
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ class VersionUpdatePopup extends StatelessWidget {
|
|||||||
|
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
final model = UpdateModel(
|
final model = UpdateModel(
|
||||||
'https://files.solsynth.dev/d/production01/solian/app-arm64-v8a-release.apk',
|
'https://files.solsynth.dev/d/c1/solian/app-arm64-v8a-release.apk',
|
||||||
'solian-app-release-${config.updatableVersion!}.apk',
|
'solian-app-release-${config.updatableVersion!}.apk',
|
||||||
'ic_launcher',
|
'ic_launcher',
|
||||||
'https://apps.apple.com/us/app/solian/id6499032345',
|
'https://apps.apple.com/us/app/solian/id6499032345',
|
||||||
|
@ -17,59 +17,59 @@ PODS:
|
|||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- file_selector_macos (0.0.1):
|
- file_selector_macos (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- Firebase/Analytics (11.8.0):
|
- Firebase/Analytics (11.10.0):
|
||||||
- Firebase/Core
|
- Firebase/Core
|
||||||
- Firebase/Core (11.8.0):
|
- Firebase/Core (11.10.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseAnalytics (~> 11.8.0)
|
- FirebaseAnalytics (~> 11.10.0)
|
||||||
- Firebase/CoreOnly (11.8.0):
|
- Firebase/CoreOnly (11.10.0):
|
||||||
- FirebaseCore (~> 11.8.0)
|
- FirebaseCore (~> 11.10.0)
|
||||||
- Firebase/Messaging (11.8.0):
|
- Firebase/Messaging (11.10.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseMessaging (~> 11.8.0)
|
- FirebaseMessaging (~> 11.10.0)
|
||||||
- firebase_analytics (11.4.4):
|
- firebase_analytics (11.4.5):
|
||||||
- Firebase/Analytics (= 11.8.0)
|
- Firebase/Analytics (= 11.10.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- firebase_core (3.12.1):
|
- firebase_core (3.13.0):
|
||||||
- Firebase/CoreOnly (~> 11.8.0)
|
- Firebase/CoreOnly (~> 11.10.0)
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- firebase_messaging (15.2.4):
|
- firebase_messaging (15.2.5):
|
||||||
- Firebase/CoreOnly (~> 11.8.0)
|
- Firebase/CoreOnly (~> 11.10.0)
|
||||||
- Firebase/Messaging (~> 11.8.0)
|
- Firebase/Messaging (~> 11.10.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- FirebaseAnalytics (11.8.0):
|
- FirebaseAnalytics (11.10.0):
|
||||||
- FirebaseAnalytics/AdIdSupport (= 11.8.0)
|
- FirebaseAnalytics/AdIdSupport (= 11.10.0)
|
||||||
- FirebaseCore (~> 11.8.0)
|
- FirebaseCore (~> 11.10.0)
|
||||||
- FirebaseInstallations (~> 11.0)
|
- FirebaseInstallations (~> 11.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.0)
|
- GoogleUtilities/MethodSwizzler (~> 8.0)
|
||||||
- GoogleUtilities/Network (~> 8.0)
|
- GoogleUtilities/Network (~> 8.0)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.0)"
|
- "GoogleUtilities/NSData+zlib (~> 8.0)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- FirebaseAnalytics/AdIdSupport (11.8.0):
|
- FirebaseAnalytics/AdIdSupport (11.10.0):
|
||||||
- FirebaseCore (~> 11.8.0)
|
- FirebaseCore (~> 11.10.0)
|
||||||
- FirebaseInstallations (~> 11.0)
|
- FirebaseInstallations (~> 11.0)
|
||||||
- GoogleAppMeasurement (= 11.8.0)
|
- GoogleAppMeasurement (= 11.10.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.0)
|
- GoogleUtilities/MethodSwizzler (~> 8.0)
|
||||||
- GoogleUtilities/Network (~> 8.0)
|
- GoogleUtilities/Network (~> 8.0)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.0)"
|
- "GoogleUtilities/NSData+zlib (~> 8.0)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- FirebaseCore (11.8.1):
|
- FirebaseCore (11.10.0):
|
||||||
- FirebaseCoreInternal (~> 11.8.0)
|
- FirebaseCoreInternal (~> 11.10.0)
|
||||||
- GoogleUtilities/Environment (~> 8.0)
|
- GoogleUtilities/Environment (~> 8.0)
|
||||||
- GoogleUtilities/Logger (~> 8.0)
|
- GoogleUtilities/Logger (~> 8.0)
|
||||||
- FirebaseCoreInternal (11.8.0):
|
- FirebaseCoreInternal (11.10.0):
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.0)"
|
- "GoogleUtilities/NSData+zlib (~> 8.0)"
|
||||||
- FirebaseInstallations (11.8.0):
|
- FirebaseInstallations (11.10.0):
|
||||||
- FirebaseCore (~> 11.8.0)
|
- FirebaseCore (~> 11.10.0)
|
||||||
- GoogleUtilities/Environment (~> 8.0)
|
- GoogleUtilities/Environment (~> 8.0)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.0)
|
- GoogleUtilities/UserDefaults (~> 8.0)
|
||||||
- PromisesObjC (~> 2.4)
|
- PromisesObjC (~> 2.4)
|
||||||
- FirebaseMessaging (11.8.0):
|
- FirebaseMessaging (11.10.0):
|
||||||
- FirebaseCore (~> 11.8.0)
|
- FirebaseCore (~> 11.10.0)
|
||||||
- FirebaseInstallations (~> 11.0)
|
- FirebaseInstallations (~> 11.0)
|
||||||
- GoogleDataTransport (~> 10.0)
|
- GoogleDataTransport (~> 10.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
||||||
@ -92,21 +92,21 @@ PODS:
|
|||||||
- gal (1.0.0):
|
- gal (1.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- GoogleAppMeasurement (11.8.0):
|
- GoogleAppMeasurement (11.10.0):
|
||||||
- GoogleAppMeasurement/AdIdSupport (= 11.8.0)
|
- GoogleAppMeasurement/AdIdSupport (= 11.10.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.0)
|
- GoogleUtilities/MethodSwizzler (~> 8.0)
|
||||||
- GoogleUtilities/Network (~> 8.0)
|
- GoogleUtilities/Network (~> 8.0)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.0)"
|
- "GoogleUtilities/NSData+zlib (~> 8.0)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- GoogleAppMeasurement/AdIdSupport (11.8.0):
|
- GoogleAppMeasurement/AdIdSupport (11.10.0):
|
||||||
- GoogleAppMeasurement/WithoutAdIdSupport (= 11.8.0)
|
- GoogleAppMeasurement/WithoutAdIdSupport (= 11.10.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.0)
|
- GoogleUtilities/MethodSwizzler (~> 8.0)
|
||||||
- GoogleUtilities/Network (~> 8.0)
|
- GoogleUtilities/Network (~> 8.0)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.0)"
|
- "GoogleUtilities/NSData+zlib (~> 8.0)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- GoogleAppMeasurement/WithoutAdIdSupport (11.8.0):
|
- GoogleAppMeasurement/WithoutAdIdSupport (11.10.0):
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.0)
|
- GoogleUtilities/MethodSwizzler (~> 8.0)
|
||||||
- GoogleUtilities/Network (~> 8.0)
|
- GoogleUtilities/Network (~> 8.0)
|
||||||
@ -365,22 +365,22 @@ SPEC CHECKSUMS:
|
|||||||
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
|
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
|
||||||
file_saver: e35bd97de451dde55ff8c38862ed7ad0f3418d0f
|
file_saver: e35bd97de451dde55ff8c38862ed7ad0f3418d0f
|
||||||
file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31
|
file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31
|
||||||
Firebase: d80354ed7f6df5f9aca55e9eb47cc4b634735eaf
|
Firebase: 1fe1c0a7d9aaea32efe01fbea5f0ebd8d70e53a2
|
||||||
firebase_analytics: 2c7864ab677e8a178a6dd4126de1d19e9d9a7bf3
|
firebase_analytics: 5f4b20b5f700bcae2f800c69a63e79d937d0daa9
|
||||||
firebase_core: 3dcdf8453dfb144a023ee70f49e0463b97177f71
|
firebase_core: efd50ad8177dc489af1b9163a560359cf1b30597
|
||||||
firebase_messaging: 96fe41b2f8b5bee4e0f21df8d716cb8c9293448c
|
firebase_messaging: acf2566068a55d7eb8cddfee5b094754070a5b88
|
||||||
FirebaseAnalytics: 4fd42def128146e24e480e89f310e3d8534ea42b
|
FirebaseAnalytics: 4e42333f02cf78ed93703a5c36f36dd518aebdef
|
||||||
FirebaseCore: 99fe0c4b44a39f37d99e6404e02009d2db5d718d
|
FirebaseCore: 8344daef5e2661eb004b177488d6f9f0f24251b7
|
||||||
FirebaseCoreInternal: df24ce5af28864660ecbd13596fc8dd3a8c34629
|
FirebaseCoreInternal: ef4505d2afb1d0ebbc33162cb3795382904b5679
|
||||||
FirebaseInstallations: 6c963bd2a86aca0481eef4f48f5a4df783ae5917
|
FirebaseInstallations: 9980995bdd06ec8081dfb6ab364162bdd64245c3
|
||||||
FirebaseMessaging: 487b634ccdf6f7b7ff180fdcb2a9935490f764e8
|
FirebaseMessaging: 2b9f56aa4ed286e1f0ce2ee1d413aabb8f9f5cb9
|
||||||
flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d
|
flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d
|
||||||
flutter_timezone: d59eea86178cbd7943cd2431cc2eaa9850f935d8
|
flutter_timezone: d59eea86178cbd7943cd2431cc2eaa9850f935d8
|
||||||
flutter_udid: d26e455e8c06174e6aff476e147defc6cae38495
|
flutter_udid: d26e455e8c06174e6aff476e147defc6cae38495
|
||||||
flutter_webrtc: 377dbcebdde6fed0fc40de87bcaaa2bffcec9a88
|
flutter_webrtc: 377dbcebdde6fed0fc40de87bcaaa2bffcec9a88
|
||||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||||
GoogleAppMeasurement: fc0817122bd4d4189164f85374e06773b9561896
|
GoogleAppMeasurement: 36684bfb3ee034e2b42b4321eb19da3a1b81e65d
|
||||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||||
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
|
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
|
||||||
HotKey: 400beb7caa29054ea8d864c96f5ba7e5b4852277
|
HotKey: 400beb7caa29054ea8d864c96f5ba7e5b4852277
|
||||||
|
@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 2.4.2+88
|
version: 2.4.2+89
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.5.4
|
sdk: ^3.5.4
|
||||||
|
Reference in New Issue
Block a user