💄 Video player optimized

This commit is contained in:
2025-08-01 20:36:39 +08:00
parent 84b1d6a346
commit b39e2e2d64
24 changed files with 500 additions and 299 deletions

View File

@@ -93,7 +93,7 @@ class _AboutScreenState extends ConsumerState<AboutScreen> {
final theme = Theme.of(context); final theme = Theme.of(context);
return AppScaffold( return AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar(title: Text('about'.tr()), elevation: 0), appBar: AppBar(title: Text('about'.tr()), elevation: 0),
body: body:
_isLoading _isLoading

View File

@@ -64,7 +64,7 @@ class AccountScreen extends HookConsumerWidget {
} }
return AppScaffold( return AppScaffold(
noBackground: isWide, isNoBackground: isWide,
appBar: AppBar(backgroundColor: Colors.transparent, toolbarHeight: 0), appBar: AppBar(backgroundColor: Colors.transparent, toolbarHeight: 0),
body: SingleChildScrollView( body: SingleChildScrollView(
padding: getTabbedPadding(context), padding: getTabbedPadding(context),

View File

@@ -46,7 +46,7 @@ class EventCalanderScreen extends HookConsumerWidget {
} }
return AppScaffold( return AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar( appBar: AppBar(
leading: const PageBackButton(), leading: const PageBackButton(),
title: Text('eventCalander').tr(), title: Text('eventCalander').tr(),

View File

@@ -12,6 +12,7 @@ import 'package:island/pods/event_calendar.dart';
import 'package:island/pods/network.dart'; import 'package:island/pods/network.dart';
import 'package:island/pods/userinfo.dart'; import 'package:island/pods/userinfo.dart';
import 'package:island/services/color.dart'; import 'package:island/services/color.dart';
import 'package:island/services/responsive.dart';
import 'package:island/services/time.dart'; import 'package:island/services/time.dart';
import 'package:island/services/timezone/native.dart'; import 'package:island/services/timezone/native.dart';
import 'package:island/widgets/account/account_name.dart'; import 'package:island/widgets/account/account_name.dart';
@@ -248,58 +249,12 @@ class AccountProfileScreen extends HookConsumerWidget {
final user = ref.watch(userInfoProvider); final user = ref.watch(userInfoProvider);
return account.when( Widget accountBasicInfo(SnAccount data) => Padding(
data:
(data) => AppScaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
foregroundColor: appbarColor.value,
expandedHeight: 180,
pinned: true,
leading: PageBackButton(
color: appbarColor.value,
shadows: [appbarShadow],
),
flexibleSpace: Stack(
children: [
Positioned.fill(
child:
data.profile.background?.id != null
? CloudImageWidget(
file: data.profile.background,
)
: Container(
color:
Theme.of(
context,
).appBarTheme.backgroundColor,
),
),
FlexibleSpaceBar(
title: Text(
data.nick,
style: TextStyle(
color:
appbarColor.value ??
Theme.of(context).appBarTheme.foregroundColor,
shadows: [appbarShadow],
),
),
),
],
),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.fromLTRB(24, 24, 24, 8), padding: const EdgeInsets.fromLTRB(24, 24, 24, 8),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ProfilePictureWidget( ProfilePictureWidget(file: data.profile.picture, radius: 32),
file: data.profile.picture,
radius: 32,
),
const Gap(20), const Gap(20),
Expanded( Expanded(
child: Column( child: Column(
@@ -307,55 +262,20 @@ class AccountProfileScreen extends HookConsumerWidget {
children: [ children: [
Row( Row(
children: [ children: [
AccountName( AccountName(account: data, style: TextStyle(fontSize: 20)),
account: data,
style: TextStyle(fontSize: 20),
),
const Gap(6), const Gap(6),
Text( Text('@${data.name}').fontSize(14).opacity(0.85),
'@${data.name}',
).fontSize(14).opacity(0.85),
], ],
), ),
AccountStatusWidget( AccountStatusWidget(uname: name, padding: EdgeInsets.zero),
uname: name,
padding: EdgeInsets.zero,
),
], ],
), ),
), ),
], ],
), ),
), );
),
if (data.badges.isNotEmpty)
SliverToBoxAdapter(
child: BadgeList(
badges: data.badges,
).padding(horizontal: 24, bottom: 24),
),
SliverToBoxAdapter(
child: Column(
spacing: 12,
children: [
LevelingProgressCard(
level: data.profile.level,
experience: data.profile.experience,
progress: data.profile.levelingProgress,
),
if (data.profile.verification != null)
VerificationStatusCard(
mark: data.profile.verification!,
),
],
).padding(horizontal: 20),
),
SliverToBoxAdapter( Widget accountProfileDetail(SnAccount data) => Column(
child: const Divider(height: 1).padding(vertical: 24),
),
SliverToBoxAdapter(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
spacing: 24, spacing: 24,
children: [ children: [
@@ -393,9 +313,7 @@ class AccountProfileScreen extends HookConsumerWidget {
).$2.formatCustomGlobal('HH:mm'), ).$2.formatCustomGlobal('HH:mm'),
), ),
Text( Text(
getTzInfo( getTzInfo(data.profile.timeZone).$1.formatOffsetLocal(),
data.profile.timeZone,
).$1.formatOffsetLocal(),
).fontSize(11), ).fontSize(11),
Text( Text(
'UTC${getTzInfo(data.profile.timeZone).$1.formatOffset()}', 'UTC${getTzInfo(data.profile.timeZone).$1.formatOffset()}',
@@ -405,18 +323,12 @@ class AccountProfileScreen extends HookConsumerWidget {
], ],
), ),
], ],
).padding(horizontal: 24), ).padding(horizontal: 24);
),
if (user.value != null) Widget accountAction(SnAccount data) => Card(
SliverToBoxAdapter( child: Column(
child: const Divider( children: [
height: 1, Row(
).padding(top: 24, bottom: 12),
),
if (user.value != null)
SliverToBoxAdapter(
child: Row(
spacing: 8, spacing: 8,
children: [ children: [
if (accountRelationship.value == null || if (accountRelationship.value == null ||
@@ -432,9 +344,7 @@ class AccountProfileScreen extends HookConsumerWidget {
foregroundColor: WidgetStatePropertyAll( foregroundColor: WidgetStatePropertyAll(
accountRelationship.value == null accountRelationship.value == null
? null ? null
: Theme.of( : Theme.of(context).colorScheme.onSecondary,
context,
).colorScheme.onSecondary,
), ),
), ),
onPressed: relationshipAction, onPressed: relationshipAction,
@@ -463,9 +373,7 @@ class AccountProfileScreen extends HookConsumerWidget {
foregroundColor: WidgetStatePropertyAll( foregroundColor: WidgetStatePropertyAll(
accountRelationship.value == null accountRelationship.value == null
? null ? null
: Theme.of( : Theme.of(context).colorScheme.onSecondary,
context,
).colorScheme.onSecondary,
), ),
), ),
onPressed: blockAction, onPressed: blockAction,
@@ -483,9 +391,7 @@ class AccountProfileScreen extends HookConsumerWidget {
), ),
], ],
).padding(horizontal: 16), ).padding(horizontal: 16),
), Row(
SliverToBoxAdapter(
child: Row(
spacing: 8, spacing: 8,
children: [ children: [
Expanded( Expanded(
@@ -519,11 +425,179 @@ class AccountProfileScreen extends HookConsumerWidget {
), ),
), ),
], ],
).padding(horizontal: 16, top: 4), ),
],
).padding(horizontal: 16, vertical: 8),
);
return account.when(
data:
(data) => AppScaffold(
isNoBackground: false,
appBar:
isWideScreen(context)
? AppBar(
foregroundColor: appbarColor.value,
leading: PageBackButton(
color: appbarColor.value,
shadows: [appbarShadow],
),
flexibleSpace: Stack(
children: [
Positioned.fill(
child:
data.profile.background?.id != null
? CloudImageWidget(
file: data.profile.background,
)
: Container(
color:
Theme.of(
context,
).appBarTheme.backgroundColor,
),
),
FlexibleSpaceBar(
title: Text(
data.nick,
style: TextStyle(
color:
appbarColor.value ??
Theme.of(
context,
).appBarTheme.foregroundColor,
shadows: [appbarShadow],
),
),
),
],
),
)
: null,
body:
isWideScreen(context)
? Row(
children: [
Flexible(
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(child: accountBasicInfo(data)),
if (data.badges.isNotEmpty)
SliverToBoxAdapter(
child: BadgeList(
badges: data.badges,
).padding(horizontal: 24, bottom: 24),
), ),
SliverToBoxAdapter( SliverToBoxAdapter(
child: const Divider(height: 1).padding(top: 12), child: Column(
spacing: 12,
children: [
LevelingProgressCard(
level: data.profile.level,
experience: data.profile.experience,
progress: data.profile.levelingProgress,
), ),
if (data.profile.verification != null)
VerificationStatusCard(
mark: data.profile.verification!,
),
],
).padding(horizontal: 20),
),
],
),
),
Flexible(
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: accountProfileDetail(data),
),
if (user.value != null)
SliverToBoxAdapter(child: accountAction(data)),
SliverToBoxAdapter(
child: Card(
child: FortuneGraphWidget(
events: accountEvents,
eventCalanderUser: data.name,
),
).padding(all: 8),
),
],
),
),
],
)
: CustomScrollView(
slivers: [
SliverAppBar(
foregroundColor: appbarColor.value,
expandedHeight: 180,
pinned: true,
leading: PageBackButton(
color: appbarColor.value,
shadows: [appbarShadow],
),
flexibleSpace: Stack(
children: [
Positioned.fill(
child:
data.profile.background?.id != null
? CloudImageWidget(
file: data.profile.background,
)
: Container(
color:
Theme.of(
context,
).appBarTheme.backgroundColor,
),
),
FlexibleSpaceBar(
title: Text(
data.nick,
style: TextStyle(
color:
appbarColor.value ??
Theme.of(
context,
).appBarTheme.foregroundColor,
shadows: [appbarShadow],
),
),
),
],
),
),
SliverToBoxAdapter(child: accountBasicInfo(data)),
if (data.badges.isNotEmpty)
SliverToBoxAdapter(
child: BadgeList(
badges: data.badges,
).padding(horizontal: 24, bottom: 24),
),
SliverToBoxAdapter(
child: Column(
spacing: 12,
children: [
LevelingProgressCard(
level: data.profile.level,
experience: data.profile.experience,
progress: data.profile.levelingProgress,
),
if (data.profile.verification != null)
VerificationStatusCard(
mark: data.profile.verification!,
),
],
).padding(horizontal: 20),
),
SliverToBoxAdapter(child: accountProfileDetail(data)),
if (user.value != null)
SliverToBoxAdapter(child: accountAction(data)),
SliverToBoxAdapter( SliverToBoxAdapter(
child: Column( child: Column(
children: [ children: [

View File

@@ -73,7 +73,7 @@ class CreateAccountScreen extends HookConsumerWidget {
} }
return AppScaffold( return AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar( appBar: AppBar(
leading: const PageBackButton(), leading: const PageBackButton(),
title: Text('createAccount').tr(), title: Text('createAccount').tr(),

View File

@@ -55,7 +55,7 @@ class LoginScreen extends HookConsumerWidget {
final factorPicked = useState<SnAuthFactor?>(null); final factorPicked = useState<SnAuthFactor?>(null);
return AppScaffold( return AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar( appBar: AppBar(
leading: const PageBackButton(), leading: const PageBackButton(),
title: Text('login').tr(), title: Text('login').tr(),

View File

@@ -40,7 +40,7 @@ class CallScreen extends HookConsumerWidget {
); );
return AppScaffold( return AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar( appBar: AppBar(
leading: PageBackButton(), leading: PageBackButton(),
title: Column( title: Column(

View File

@@ -111,7 +111,7 @@ class DeveloperHubScreen extends HookConsumerWidget {
); );
return AppScaffold( return AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar( appBar: AppBar(
leading: !isWide ? const PageBackButton() : null, leading: !isWide ? const PageBackButton() : null,
title: Text('developerHub').tr(), title: Text('developerHub').tr(),

View File

@@ -17,7 +17,7 @@ class DiscoveryRealmsScreen extends HookConsumerWidget {
final currentQuery = useState<String?>(null); final currentQuery = useState<String?>(null);
return AppScaffold( return AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar(title: Text('discoverRealms'.tr())), appBar: AppBar(title: Text('discoverRealms'.tr())),
body: Stack( body: Stack(
children: [ children: [

View File

@@ -87,7 +87,7 @@ class ExploreScreen extends HookConsumerWidget {
final user = ref.watch(userInfoProvider); final user = ref.watch(userInfoProvider);
return AppScaffold( return AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar( appBar: AppBar(
toolbarHeight: 0, toolbarHeight: 0,
bottom: PreferredSize( bottom: PreferredSize(

View File

@@ -53,13 +53,13 @@ class PostEditScreen extends HookConsumerWidget {
data: (post) => PostComposeScreen(originalPost: post), data: (post) => PostComposeScreen(originalPost: post),
loading: loading:
() => AppScaffold( () => AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar(leading: const PageBackButton()), appBar: AppBar(leading: const PageBackButton()),
body: const Center(child: CircularProgressIndicator()), body: const Center(child: CircularProgressIndicator()),
), ),
error: error:
(e, _) => AppScaffold( (e, _) => AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar(leading: const PageBackButton()), appBar: AppBar(leading: const PageBackButton()),
body: Text('Error: $e', textAlign: TextAlign.center), body: Text('Error: $e', textAlign: TextAlign.center),
), ),
@@ -287,7 +287,7 @@ class PostComposeScreen extends HookConsumerWidget {
} }
}, },
child: AppScaffold( child: AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar( appBar: AppBar(
leading: const PageBackButton(), leading: const PageBackButton(),
actions: [ actions: [

View File

@@ -352,7 +352,7 @@ class ArticleComposeScreen extends HookConsumerWidget {
} }
}, },
child: AppScaffold( child: AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar( appBar: AppBar(
leading: const PageBackButton(), leading: const PageBackButton(),
title: ValueListenableBuilder<TextEditingValue>( title: ValueListenableBuilder<TextEditingValue>(

View File

@@ -54,7 +54,7 @@ class PostDetailScreen extends HookConsumerWidget {
final user = ref.watch(userInfoProvider); final user = ref.watch(userInfoProvider);
return AppScaffold( return AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar(title: const Text('Post')), appBar: AppBar(title: const Text('Post')),
body: postState.when( body: postState.when(
data: (post) { data: (post) {

View File

@@ -110,7 +110,7 @@ class _PostSearchScreenState extends ConsumerState<PostSearchScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AppScaffold( return AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar( appBar: AppBar(
title: TextField( title: TextField(
controller: _searchController, controller: _searchController,

View File

@@ -259,7 +259,7 @@ class PublisherProfileScreen extends HookConsumerWidget {
return publisher.when( return publisher.when(
data: data:
(data) => AppScaffold( (data) => AppScaffold(
noBackground: false, isNoBackground: false,
appBar: appBar:
isWideScreen(context) isWideScreen(context)
? AppBar( ? AppBar(
@@ -389,13 +389,13 @@ class PublisherProfileScreen extends HookConsumerWidget {
), ),
error: error:
(error, stackTrace) => AppScaffold( (error, stackTrace) => AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar(leading: const PageBackButton()), appBar: AppBar(leading: const PageBackButton()),
body: Center(child: Text(error.toString())), body: Center(child: Text(error.toString())),
), ),
loading: loading:
() => AppScaffold( () => AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar(leading: const PageBackButton()), appBar: AppBar(leading: const PageBackButton()),
body: Center(child: CircularProgressIndicator()), body: Center(child: CircularProgressIndicator()),
), ),

View File

@@ -79,7 +79,7 @@ class RealmDetailScreen extends HookConsumerWidget {
); );
return AppScaffold( return AppScaffold(
noBackground: false, isNoBackground: false,
body: realmState.when( body: realmState.when(
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const Center(child: CircularProgressIndicator()),
error: (error, _) => Center(child: Text('Error: $error')), error: (error, _) => Center(child: Text('Error: $error')),

View File

@@ -41,7 +41,7 @@ class RealmListScreen extends HookConsumerWidget {
final realmInvites = ref.watch(realmInvitesProvider); final realmInvites = ref.watch(realmInvitesProvider);
return AppScaffold( return AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar( appBar: AppBar(
title: const Text('realms').tr(), title: const Text('realms').tr(),
actions: [ actions: [
@@ -279,7 +279,7 @@ class EditRealmScreen extends HookConsumerWidget {
} }
return AppScaffold( return AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar( appBar: AppBar(
title: Text(slug == null ? 'createRealm'.tr() : 'editRealm'.tr()), title: Text(slug == null ? 'createRealm'.tr() : 'editRealm'.tr()),
leading: const PageBackButton(), leading: const PageBackButton(),

View File

@@ -552,7 +552,7 @@ class SettingsScreen extends HookConsumerWidget {
} }
return AppScaffold( return AppScaffold(
noBackground: false, isNoBackground: false,
appBar: AppBar( appBar: AppBar(
title: Text('settings').tr(), title: Text('settings').tr(),
actions: actions:

View File

@@ -165,7 +165,7 @@ class AppScaffold extends StatelessWidget {
final AppBar? appBar; final AppBar? appBar;
final DrawerCallback? onDrawerChanged; final DrawerCallback? onDrawerChanged;
final DrawerCallback? onEndDrawerChanged; final DrawerCallback? onEndDrawerChanged;
final bool? noBackground; final bool? isNoBackground;
final bool? extendBody; final bool? extendBody;
const AppScaffold({ const AppScaffold({
@@ -181,7 +181,7 @@ class AppScaffold extends StatelessWidget {
this.endDrawer, this.endDrawer,
this.onDrawerChanged, this.onDrawerChanged,
this.onEndDrawerChanged, this.onEndDrawerChanged,
this.noBackground, this.isNoBackground,
this.extendBody, this.extendBody,
}); });
@@ -190,7 +190,7 @@ class AppScaffold extends StatelessWidget {
final appBarHeight = appBar?.preferredSize.height ?? 0; final appBarHeight = appBar?.preferredSize.height ?? 0;
final safeTop = MediaQuery.of(context).padding.top; final safeTop = MediaQuery.of(context).padding.top;
final noBackground = this.noBackground ?? isWideScreen(context); final noBackground = isNoBackground ?? isWideScreen(context);
final content = Column( final content = Column(
children: [ children: [

View File

@@ -1,8 +1,11 @@
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/file.dart'; import 'package:island/models/file.dart';
import 'package:island/pods/config.dart'; import 'package:island/pods/config.dart';
import 'package:island/services/time.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
@@ -45,7 +48,7 @@ class CloudFileWidget extends ConsumerWidget {
), ),
"video" => AspectRatio( "video" => AspectRatio(
aspectRatio: ratio, aspectRatio: ratio,
child: UniversalVideo(uri: uri, aspectRatio: ratio), child: CloudVideoWidget(item: item),
), ),
_ => Text('Unable render for ${item.mimeType}'), _ => Text('Unable render for ${item.mimeType}'),
}; };
@@ -58,6 +61,119 @@ class CloudFileWidget extends ConsumerWidget {
} }
} }
class CloudVideoWidget extends HookConsumerWidget {
final SnCloudFile item;
const CloudVideoWidget({super.key, required this.item});
@override
Widget build(BuildContext context, WidgetRef ref) {
final open = useState(false);
final serverUrl = ref.watch(serverUrlProvider);
final uri = '$serverUrl/drive/files/${item.id}';
var ratio =
item.fileMeta?['ratio'] is num
? item.fileMeta!['ratio'].toDouble()
: 1.0;
if (ratio == 0) ratio = 1.0;
if (open.value) {
return UniversalVideo(uri: uri, aspectRatio: ratio, autoplay: true);
}
return GestureDetector(
child: Stack(
children: [
UniversalImage(uri: '$uri?thumbnail=true'),
Positioned.fill(
child: Center(
child: const Icon(
Symbols.play_arrow,
fill: 1,
size: 32,
shadows: [
BoxShadow(
color: Colors.black54,
offset: Offset(1, 1),
spreadRadius: 8,
blurRadius: 8,
),
],
),
),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
spacing: 8,
children: [
if (item.fileMeta?['duration'] != null)
Text(
Duration(
milliseconds:
((item.fileMeta?['duration'] as num) * 1000)
.toInt(),
).formatDuration(),
style: TextStyle(
shadows: [
BoxShadow(
color: Colors.black54,
offset: Offset(1, 1),
spreadRadius: 8,
blurRadius: 8,
),
],
),
),
if (item.fileMeta?['bit_rate'] != null)
Text(
'${int.parse(item.fileMeta?['bit_rate'] as String) ~/ 1000} Kbps',
style: TextStyle(
shadows: [
BoxShadow(
color: Colors.black54,
offset: Offset(1, 1),
spreadRadius: 8,
blurRadius: 8,
),
],
),
),
],
),
Text(
item.name,
style: TextStyle(
fontWeight: FontWeight.bold,
shadows: [
BoxShadow(
color: Colors.black54,
offset: Offset(1, 1),
spreadRadius: 8,
blurRadius: 8,
),
],
),
),
],
),
).padding(horizontal: 16, bottom: 12),
],
),
onTap: () {
open.value = true;
},
);
}
}
class CloudImageWidget extends ConsumerWidget { class CloudImageWidget extends ConsumerWidget {
final String? fileId; final String? fileId;
final SnCloudFile? file; final SnCloudFile? file;

View File

@@ -11,10 +11,12 @@ import 'package:media_kit_video/media_kit_video.dart';
class UniversalVideo extends ConsumerStatefulWidget { class UniversalVideo extends ConsumerStatefulWidget {
final String uri; final String uri;
final double aspectRatio; final double aspectRatio;
final bool autoplay;
const UniversalVideo({ const UniversalVideo({
super.key, super.key,
required this.uri, required this.uri,
this.aspectRatio = 16 / 9, this.aspectRatio = 16 / 9,
this.autoplay = false,
}); });
@override @override
@@ -47,7 +49,7 @@ class _UniversalVideoState extends ConsumerState<UniversalVideo> {
log('[MediaPlayer] Hit cache: $url'); log('[MediaPlayer] Hit cache: $url');
} }
_player!.open(Media(uri), play: false); _player!.open(Media(uri), play: widget.autoplay);
} }
@override @override

View File

@@ -27,9 +27,13 @@ class PublisherCard extends ConsumerWidget {
Widget card = Card( Widget card = Card(
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
margin: EdgeInsets.zero,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
context.pushNamed('publisherProfile', pathParameters: {'name': publisher.name}); context.pushNamed(
'publisherProfile',
pathParameters: {'name': publisher.name},
);
}, },
child: AspectRatio( child: AspectRatio(
aspectRatio: 16 / 7, aspectRatio: 16 / 7,

View File

@@ -29,9 +29,13 @@ class RealmCard extends ConsumerWidget {
Widget card = Card( Widget card = Card(
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
margin: EdgeInsets.zero,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
context.pushNamed('realmDetail', pathParameters: {'slug': realm.slug}); context.pushNamed(
'realmDetail',
pathParameters: {'slug': realm.slug},
);
}, },
child: AspectRatio( child: AspectRatio(
aspectRatio: 16 / 7, aspectRatio: 16 / 7,

View File

@@ -28,6 +28,7 @@ class WebArticleCard extends StatelessWidget {
return ConstrainedBox( return ConstrainedBox(
constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity), constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity),
child: Card( child: Card(
margin: EdgeInsets.zero,
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
child: InkWell( child: InkWell(
onTap: () => _onTap(context), onTap: () => _onTap(context),