💄 Video player optimized
This commit is contained in:
@@ -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
|
||||||
|
@@ -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),
|
||||||
|
@@ -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(),
|
||||||
|
@@ -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: [
|
||||||
|
@@ -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(),
|
||||||
|
@@ -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(),
|
||||||
|
@@ -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(
|
||||||
|
@@ -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(),
|
||||||
|
@@ -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: [
|
||||||
|
@@ -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(
|
||||||
|
@@ -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: [
|
||||||
|
@@ -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>(
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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,
|
||||||
|
@@ -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()),
|
||||||
),
|
),
|
||||||
|
@@ -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')),
|
||||||
|
@@ -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(),
|
||||||
|
@@ -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:
|
||||||
|
@@ -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: [
|
||||||
|
@@ -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;
|
||||||
|
@@ -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
|
||||||
|
@@ -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,
|
||||||
|
@@ -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,
|
||||||
|
@@ -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),
|
||||||
|
Reference in New Issue
Block a user