Compare commits

..

No commits in common. "b5155ebc5f667e15d56f9a08caa4b2433bd2807e" and "f311c1898c968fb479c8d0a6202fc1c719e5c470" have entirely different histories.

5 changed files with 89 additions and 128 deletions

View File

@ -15,6 +15,7 @@ import 'package:surface/providers/websocket.dart';
import 'package:surface/types/account.dart'; import 'package:surface/types/account.dart';
import 'package:surface/widgets/account/account_image.dart'; import 'package:surface/widgets/account/account_image.dart';
import 'package:surface/widgets/account/account_status.dart'; import 'package:surface/widgets/account/account_status.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/navigation/app_scaffold.dart'; import 'package:surface/widgets/navigation/app_scaffold.dart';
import 'package:surface/widgets/universal_image.dart'; import 'package:surface/widgets/universal_image.dart';
@ -111,7 +112,7 @@ class AccountScreen extends StatelessWidget {
return AppScaffold( return AppScaffold(
noBackground: ResponsiveScaffold.getIsExpand(context), noBackground: ResponsiveScaffold.getIsExpand(context),
appBar: AppBar( appBar: AppBar(
leading: const PageBackButton(), leading: AutoAppBarLeading(),
title: Text("screenAccount").tr(), title: Text("screenAccount").tr(),
flexibleSpace: ua.user != null && ua.user!.banner.isNotEmpty flexibleSpace: ua.user != null && ua.user!.banner.isNotEmpty
? Stack( ? Stack(

View File

@ -1,21 +1,19 @@
import 'package:dismissible_page/dismissible_page.dart'; import 'package:dismissible_page/dismissible_page.dart';
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_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:gap/gap.dart'; import 'package:gap/gap.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/path.dart' show withoutExtension;
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/sn_network.dart'; import 'package:surface/providers/sn_network.dart';
import 'package:surface/providers/userinfo.dart';
import 'package:surface/types/attachment.dart'; import 'package:surface/types/attachment.dart';
import 'package:surface/widgets/attachment/attachment_item.dart';
import 'package:surface/widgets/attachment/attachment_zoom.dart'; import 'package:surface/widgets/attachment/attachment_zoom.dart';
import 'package:surface/widgets/attachment/attachment_item.dart';
import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/dialog.dart';
import 'package:surface/widgets/navigation/app_scaffold.dart'; import 'package:surface/widgets/navigation/app_scaffold.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
class AlbumScreen extends StatefulWidget { class AlbumScreen extends StatefulWidget {
const AlbumScreen({super.key}); const AlbumScreen({super.key});
@ -50,8 +48,6 @@ class _AlbumScreenState extends State<AlbumScreen> {
Future<void> _fetchAttachments() async { Future<void> _fetchAttachments() async {
setState(() => _isBusy = true); setState(() => _isBusy = true);
final ua = context.read<UserProvider>();
const uuid = Uuid(); const uuid = Uuid();
try { try {
@ -59,11 +55,10 @@ class _AlbumScreenState extends State<AlbumScreen> {
final resp = await sn.client.get('/cgi/uc/attachments', queryParameters: { final resp = await sn.client.get('/cgi/uc/attachments', queryParameters: {
'take': 10, 'take': 10,
'offset': _attachments.length, 'offset': _attachments.length,
'author': ua.user?.name,
}); });
final attachments = List<SnAttachment>.from( final attachments = List<SnAttachment>.from(
resp.data['data']?.map((e) => SnAttachment.fromJson(e)) ?? [], resp.data['data']?.map((e) => SnAttachment.fromJson(e)) ?? [],
); ).where((e) => e.mimetype.startsWith('image')).toList();
_attachments.addAll(attachments); _attachments.addAll(attachments);
_heroTags.addAll(_attachments.map((_) => uuid.v4())); _heroTags.addAll(_attachments.map((_) => uuid.v4()));
@ -102,14 +97,15 @@ class _AlbumScreenState extends State<AlbumScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AppScaffold( return AppScaffold(
appBar: AppBar( body: CustomScrollView(
controller: _scrollController,
slivers: [
SliverAppBar(
leading: PageBackButton(), leading: PageBackButton(),
title: Text('screenAlbum').tr(), title: Text('screenAlbum').tr(),
), ),
body: Column( SliverToBoxAdapter(
children: [ child: Card(
Card(
margin: EdgeInsets.zero,
child: Row( child: Row(
children: [ children: [
SizedBox( SizedBox(
@ -129,7 +125,8 @@ class _AlbumScreenState extends State<AlbumScreen> {
children: [ children: [
Text('attachmentBillingUploaded').tr().bold(), Text('attachmentBillingUploaded').tr().bold(),
Text( Text(
(_billing?.currentBytes ?? 0).formatBytes(decimals: 4), (_billing?.currentBytes ?? 0)
.formatBytes(decimals: 4),
style: GoogleFonts.robotoMono(), style: GoogleFonts.robotoMono(),
), ),
Text('attachmentBillingDiscount').tr().bold(), Text('attachmentBillingDiscount').tr().bold(),
@ -149,82 +146,47 @@ class _AlbumScreenState extends State<AlbumScreen> {
), ),
], ],
).padding(horizontal: 24, vertical: 8), ).padding(horizontal: 24, vertical: 8),
).padding(horizontal: 8, top: 8), ),
Expanded( ),
child: InfiniteList( SliverMasonryGrid.extent(
padding: EdgeInsets.only(top: 8), childCount: _attachments.length,
itemCount: _attachments.length, maxCrossAxisExtent: 320,
isLoading: _isBusy, mainAxisSpacing: 4,
hasReachedMax: crossAxisSpacing: 4,
_totalCount != null && _attachments.length >= _totalCount!, itemBuilder: (context, idx) {
onFetchData: _fetchAttachments, final attachment = _attachments[idx];
itemBuilder: (context, index) { return GestureDetector(
final ele = _attachments[index]; child: ClipRRect(
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipRRect(
child: AspectRatio( child: AspectRatio(
aspectRatio: (ele.data['ratio'] ?? 1).toDouble(), aspectRatio: attachment.metadata['ratio']?.toDouble() ?? 1,
child: AttachmentItem( child: AttachmentItem(
data: ele, data: attachment,
heroTag: _heroTags[index], heroTag: _heroTags[idx],
onZoom: () { ),
),
),
onTap: () {
context.pushTransparentRoute( context.pushTransparentRoute(
AttachmentZoomView( AttachmentZoomView(
data: [ele], data: [attachment],
heroTags: [_heroTags[idx]],
), ),
backgroundColor: Colors.black.withOpacity(0.7), backgroundColor: Colors.black.withOpacity(0.7),
rootNavigator: true, rootNavigator: true,
); );
}, },
),
),
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(ele.name),
if (ele.alt != withoutExtension(ele.name))
Text(ele.alt),
Text(DateFormat().format(ele.createdAt)),
const Gap(4),
Text(ele.size.formatBytes()).fontSize(12),
],
).padding(horizontal: 16, vertical: 12),
),
Padding(
padding: EdgeInsets.only(left: 12, right: 12, top: 4),
child: IconButton(
padding: EdgeInsets.zero,
visualDensity: VisualDensity.compact,
icon: const Icon(Symbols.info),
onPressed: () {
showModalBottomSheet(
context: context,
builder: (context) => AttachmentZoomDetailPopup(
data: ele,
),
); );
}, },
), ),
if (_isBusy)
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(24),
child: const CircularProgressIndicator(),
).center(),
), ),
], ],
), ),
],
);
},
separatorBuilder: (_, __) => const Gap(8),
),
)
],
),
); );
} }
} }

View File

@ -303,7 +303,6 @@ class _PostPublisherScreenState extends State<PostPublisherScreen>
), ),
child: SliverAppBar( child: SliverAppBar(
expandedHeight: _appBarHeight, expandedHeight: _appBarHeight,
leading: const PageBackButton(),
title: _publisher == null title: _publisher == null
? Text('loading').tr() ? Text('loading').tr()
: RichText( : RichText(

View File

@ -373,7 +373,7 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
_showDetail = true; _showDetail = true;
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
builder: (context) => AttachmentZoomDetailPopup( builder: (context) => _AttachmentZoomDetailPopup(
data: widget.data.elementAt(_page), data: widget.data.elementAt(_page),
), ),
).then((_) { ).then((_) {
@ -403,7 +403,7 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
_showDetail = true; _showDetail = true;
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
builder: (context) => AttachmentZoomDetailPopup( builder: (context) => _AttachmentZoomDetailPopup(
data: widget.data.elementAt(_page), data: widget.data.elementAt(_page),
), ),
).then((_) { ).then((_) {
@ -416,10 +416,10 @@ class _AttachmentZoomViewState extends State<AttachmentZoomView> {
} }
} }
class AttachmentZoomDetailPopup extends StatelessWidget { class _AttachmentZoomDetailPopup extends StatelessWidget {
final SnAttachment data; final SnAttachment data;
const AttachmentZoomDetailPopup({required this.data}); const _AttachmentZoomDetailPopup({required this.data});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -40,7 +40,6 @@ class UnauthorizedHint extends StatelessWidget {
GoRouter.of(context).pushNamed('authLogin').then((value) { GoRouter.of(context).pushNamed('authLogin').then((value) {
if (value == true && context.mounted) { if (value == true && context.mounted) {
final ua = context.read<UserProvider>(); final ua = context.read<UserProvider>();
ua.refreshUser();
context.showSnackbar('loginSuccess'.tr(args: [ context.showSnackbar('loginSuccess'.tr(args: [
'@${ua.user?.name} (${ua.user?.nick})', '@${ua.user?.name} (${ua.user?.nick})',
])); ]));