mirror of
https://github.com/wgh136/pixes.git
synced 2025-09-27 12:57:24 +00:00
improve mobile ui
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:pixes/foundation/app.dart';
|
||||
|
||||
class SliverGridViewWithFixedItemHeight extends StatelessWidget {
|
||||
const SliverGridViewWithFixedItemHeight(
|
||||
@@ -22,7 +23,7 @@ class SliverGridViewWithFixedItemHeight extends StatelessWidget {
|
||||
maxCrossAxisExtent: maxCrossAxisExtent,
|
||||
childAspectRatio:
|
||||
calcChildAspectRatio(constraints.crossAxisExtent)),
|
||||
)));
|
||||
).sliverPadding(EdgeInsets.only(bottom: context.padding.bottom))));
|
||||
}
|
||||
|
||||
double calcChildAspectRatio(double width) {
|
||||
@@ -61,6 +62,7 @@ class GridViewWithFixedItemHeight extends StatelessWidget {
|
||||
calcChildAspectRatio(constraints.maxWidth)),
|
||||
itemBuilder: builder,
|
||||
itemCount: itemCount,
|
||||
padding: EdgeInsets.only(bottom: context.padding.bottom),
|
||||
)));
|
||||
}
|
||||
|
||||
|
@@ -16,4 +16,8 @@ extension Navigation on BuildContext {
|
||||
void showToast({required String message, IconData? icon}) {
|
||||
overlay.showToast(this, message: message, icon: icon);
|
||||
}
|
||||
|
||||
Size get size => MediaQuery.of(this).size;
|
||||
|
||||
EdgeInsets get padding => MediaQuery.of(this).padding;
|
||||
}
|
||||
|
103
lib/main.dart
103
lib/main.dart
@@ -1,4 +1,5 @@
|
||||
import "package:fluent_ui/fluent_ui.dart";
|
||||
import "package:flutter/services.dart";
|
||||
import "package:pixes/appdata.dart";
|
||||
import "package:pixes/components/message.dart";
|
||||
import "package:pixes/foundation/app.dart";
|
||||
@@ -43,55 +44,61 @@ class MyApp extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StateBuilder<SimpleController>(
|
||||
init: SimpleController(),
|
||||
tag: "MyApp",
|
||||
builder: (controller) {
|
||||
return FluentApp(
|
||||
navigatorKey: App.rootNavigatorKey,
|
||||
debugShowCheckedModeBanner: false,
|
||||
title: 'pixes',
|
||||
theme: FluentThemeData(
|
||||
brightness: Brightness.light,
|
||||
fontFamily: App.isWindows ? 'font' : null,
|
||||
accentColor: AccentColor.swatch({
|
||||
'darkest': SystemTheme.accentColor.darkest,
|
||||
'darker': SystemTheme.accentColor.darker,
|
||||
'dark': SystemTheme.accentColor.dark,
|
||||
'normal': SystemTheme.accentColor.accent,
|
||||
'light': SystemTheme.accentColor.light,
|
||||
'lighter': SystemTheme.accentColor.lighter,
|
||||
'lightest': SystemTheme.accentColor.lightest,
|
||||
})),
|
||||
darkTheme: FluentThemeData(
|
||||
brightness: Brightness.dark,
|
||||
fontFamily: App.isWindows ? 'font' : null,
|
||||
accentColor: AccentColor.swatch({
|
||||
'darkest': SystemTheme.accentColor.darkest,
|
||||
'darker': SystemTheme.accentColor.darker,
|
||||
'dark': SystemTheme.accentColor.dark,
|
||||
'normal': SystemTheme.accentColor.accent,
|
||||
'light': SystemTheme.accentColor.light,
|
||||
'lighter': SystemTheme.accentColor.lighter,
|
||||
'lightest': SystemTheme.accentColor.lightest,
|
||||
})),
|
||||
home: const MainPage(),
|
||||
builder: (context, child) {
|
||||
ErrorWidget.builder = (details) {
|
||||
if (details.exception
|
||||
.toString()
|
||||
.contains("RenderFlex overflowed")) {
|
||||
return const SizedBox.shrink();
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||
value: const SystemUiOverlayStyle(
|
||||
systemNavigationBarColor: Colors.transparent,
|
||||
statusBarColor: Colors.transparent),
|
||||
child: StateBuilder<SimpleController>(
|
||||
init: SimpleController(),
|
||||
tag: "MyApp",
|
||||
builder: (controller) {
|
||||
return FluentApp(
|
||||
navigatorKey: App.rootNavigatorKey,
|
||||
debugShowCheckedModeBanner: false,
|
||||
title: 'pixes',
|
||||
theme: FluentThemeData(
|
||||
brightness: Brightness.light,
|
||||
fontFamily: App.isWindows ? 'font' : null,
|
||||
accentColor: AccentColor.swatch({
|
||||
'darkest': SystemTheme.accentColor.darkest,
|
||||
'darker': SystemTheme.accentColor.darker,
|
||||
'dark': SystemTheme.accentColor.dark,
|
||||
'normal': SystemTheme.accentColor.accent,
|
||||
'light': SystemTheme.accentColor.light,
|
||||
'lighter': SystemTheme.accentColor.lighter,
|
||||
'lightest': SystemTheme.accentColor.lightest,
|
||||
})),
|
||||
darkTheme: FluentThemeData(
|
||||
brightness: Brightness.dark,
|
||||
fontFamily: App.isWindows ? 'font' : null,
|
||||
accentColor: AccentColor.swatch({
|
||||
'darkest': SystemTheme.accentColor.darkest,
|
||||
'darker': SystemTheme.accentColor.darker,
|
||||
'dark': SystemTheme.accentColor.dark,
|
||||
'normal': SystemTheme.accentColor.accent,
|
||||
'light': SystemTheme.accentColor.light,
|
||||
'lighter': SystemTheme.accentColor.lighter,
|
||||
'lightest': SystemTheme.accentColor.lightest,
|
||||
})),
|
||||
home: const MainPage(),
|
||||
builder: (context, child) {
|
||||
ErrorWidget.builder = (details) {
|
||||
if (details.exception
|
||||
.toString()
|
||||
.contains("RenderFlex overflowed")) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
Log.error("UI", "${details.exception}\n${details.stack}");
|
||||
return Text(details.exception.toString());
|
||||
};
|
||||
if (child == null) {
|
||||
throw "widget is null";
|
||||
}
|
||||
Log.error("UI", "${details.exception}\n${details.stack}");
|
||||
return Text(details.exception.toString());
|
||||
};
|
||||
if (child == null) {
|
||||
throw "widget is null";
|
||||
}
|
||||
|
||||
return OverlayWidget(child);
|
||||
});
|
||||
});
|
||||
return OverlayWidget(child);
|
||||
});
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ import 'package:fluent_ui/fluent_ui.dart';
|
||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||
import 'package:pixes/components/segmented_button.dart';
|
||||
import 'package:pixes/components/title_bar.dart';
|
||||
import 'package:pixes/foundation/app.dart';
|
||||
import 'package:pixes/network/network.dart';
|
||||
import 'package:pixes/utils/translation.dart';
|
||||
|
||||
@@ -65,7 +66,8 @@ class _OneBookmarkedPageState extends MultiPageLoadingState<_OneBookmarkedPage,
|
||||
Widget buildContent(BuildContext context, final List<Illust> data) {
|
||||
return LayoutBuilder(builder: (context, constrains){
|
||||
return MasonryGridView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8)
|
||||
+ EdgeInsets.only(bottom: context.padding.bottom),
|
||||
gridDelegate: const SliverSimpleGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 240,
|
||||
),
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart';
|
||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||
import 'package:pixes/components/title_bar.dart';
|
||||
import 'package:pixes/foundation/app.dart';
|
||||
import 'package:pixes/utils/translation.dart';
|
||||
|
||||
import '../components/illust_widget.dart';
|
||||
@@ -66,7 +67,8 @@ class _OneFollowingPageState extends MultiPageLoadingState<_OneFollowingPage, Il
|
||||
Widget buildContent(BuildContext context, final List<Illust> data) {
|
||||
return LayoutBuilder(builder: (context, constrains){
|
||||
return MasonryGridView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8)
|
||||
+ EdgeInsets.only(bottom: context.padding.bottom),
|
||||
gridDelegate: const SliverSimpleGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 240,
|
||||
),
|
||||
|
@@ -88,8 +88,8 @@ class _IllustPageState extends State<IllustPage> {
|
||||
downloadFile = DownloadManager().getImage(widget.illust.id, index);
|
||||
}
|
||||
if (index == widget.illust.images.length) {
|
||||
return const SizedBox(
|
||||
height: _kBottomBarHeight,
|
||||
return SizedBox(
|
||||
height: _kBottomBarHeight + context.padding.bottom,
|
||||
);
|
||||
}
|
||||
var imageWidth = width;
|
||||
@@ -174,7 +174,7 @@ class _BottomBarState extends State<_BottomBar> with TickerProviderStateMixin{
|
||||
late final AnimationController animationController;
|
||||
|
||||
double get minValue => pageHeight - widgetHeight;
|
||||
double get maxValue => pageHeight - _kBottomBarHeight;
|
||||
double get maxValue => pageHeight - _kBottomBarHeight - context.padding.bottom;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -200,7 +200,7 @@ class _BottomBarState extends State<_BottomBar> with TickerProviderStateMixin{
|
||||
void _handlePointerMove(DragUpdateDetails details) {
|
||||
var offset = details.primaryDelta ?? 0;
|
||||
final minValue = pageHeight - widgetHeight;
|
||||
final maxValue = pageHeight - _kBottomBarHeight;
|
||||
final maxValue = pageHeight - _kBottomBarHeight - context.padding.bottom;
|
||||
var top = animationController.value * (maxValue - minValue) + minValue;
|
||||
top = (top + offset).clamp(minValue, maxValue);
|
||||
animationController.value = (top - minValue) / (maxValue - minValue);
|
||||
@@ -292,7 +292,7 @@ class _BottomBarState extends State<_BottomBar> with TickerProviderStateMixin{
|
||||
buildTags(),
|
||||
buildMoreActions(),
|
||||
SelectableText("${"Artwork ID".tl}: ${widget.illust.id}\n${"Artist ID".tl}: ${widget.illust.author.id}", style: TextStyle(color: ColorScheme.of(context).outline),).paddingLeft(4),
|
||||
const SizedBox(height: 8,)
|
||||
SizedBox(height: 8 + context.padding.bottom,)
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -361,7 +361,7 @@ class _BottomBarState extends State<_BottomBar> with TickerProviderStateMixin{
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: SizedBox(
|
||||
height: double.infinity,
|
||||
width: showUserName ? 246 : 128,
|
||||
width: showUserName ? 246 : 136,
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
@@ -866,7 +866,7 @@ class _CommentsPageState extends MultiPageLoadingState<_CommentsPage, Comment> {
|
||||
});
|
||||
},
|
||||
).paddingVertical(8).paddingHorizontal(12),
|
||||
),
|
||||
).paddingBottom(context.padding.bottom),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -130,7 +130,14 @@ class _ImagePageState extends State<ImagePage> with WindowListener {
|
||||
MenuFlyoutItem(text: Text("Share".tl), onPressed: () async{
|
||||
var file = await getFile();
|
||||
if(file != null){
|
||||
var ext = file.path.split('.').last;
|
||||
var fileName = file.path.split('/').last;
|
||||
String ext;
|
||||
if(!file.path.split('.').last.contains('.')){
|
||||
ext = 'jpg';
|
||||
fileName += '.jpg';
|
||||
} else {
|
||||
ext = file.path.split('.').last;
|
||||
}
|
||||
var mediaType = switch(ext){
|
||||
'jpg' => 'image/jpeg',
|
||||
'jpeg' => 'image/jpeg',
|
||||
@@ -139,7 +146,7 @@ class _ImagePageState extends State<ImagePage> with WindowListener {
|
||||
'webp' => 'image/webp',
|
||||
_ => 'application/octet-stream'
|
||||
};
|
||||
Share.shareXFiles([XFile(file.path, mimeType: mediaType, name: file.path.split('/').last)]);
|
||||
Share.shareXFiles([XFile(file.path, mimeType: mediaType, name: fileName)]);
|
||||
}
|
||||
}),
|
||||
],
|
||||
|
@@ -85,7 +85,8 @@ class _OneRankingPageState extends MultiPageLoadingState<_OneRankingPage, Illust
|
||||
Widget buildContent(BuildContext context, final List<Illust> data) {
|
||||
return LayoutBuilder(builder: (context, constrains){
|
||||
return MasonryGridView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8)
|
||||
+ EdgeInsets.only(bottom: context.padding.bottom),
|
||||
gridDelegate: const SliverSimpleGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 240,
|
||||
),
|
||||
|
@@ -69,7 +69,8 @@ class _RecommendationArtworksPageState extends MultiPageLoadingState<_Recommenda
|
||||
Widget buildContent(BuildContext context, final List<Illust> data) {
|
||||
return LayoutBuilder(builder: (context, constrains){
|
||||
return MasonryGridView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8)
|
||||
+ EdgeInsets.only(bottom: context.padding.bottom),
|
||||
gridDelegate: const SliverSimpleGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 240,
|
||||
),
|
||||
|
@@ -172,7 +172,8 @@ class _TrendingTagsViewState extends LoadingState<_TrendingTagsView, List<Trendi
|
||||
@override
|
||||
Widget buildContent(BuildContext context, List<TrendingTag> data) {
|
||||
return MasonryGridView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0)
|
||||
+ EdgeInsets.only(bottom: context.padding.bottom),
|
||||
gridDelegate: const SliverSimpleGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 240,
|
||||
),
|
||||
@@ -336,6 +337,7 @@ class _SearchSettingsState extends State<SearchSettings> {
|
||||
)
|
||||
).toList(),
|
||||
)),
|
||||
SizedBox(height: context.padding.bottom,)
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -386,7 +388,8 @@ class _SearchResultPageState extends MultiPageLoadingState<SearchResultPage, Ill
|
||||
},
|
||||
childCount: data.length,
|
||||
),
|
||||
).sliverPaddingHorizontal(8)
|
||||
).sliverPaddingHorizontal(8),
|
||||
SliverPadding(padding: EdgeInsets.only(bottom: context.padding.bottom),)
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -440,7 +443,8 @@ class _SearchUserResultPageState extends MultiPageLoadingState<SearchUserResultP
|
||||
),
|
||||
maxCrossAxisExtent: 520,
|
||||
itemHeight: 114,
|
||||
).sliverPaddingHorizontal(8)
|
||||
).sliverPaddingHorizontal(8),
|
||||
SliverPadding(padding: EdgeInsets.only(bottom: context.padding.bottom),)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
||||
SliverTitleBar(title: "Settings".tl),
|
||||
buildHeader("Account".tl),
|
||||
buildAccount(),
|
||||
SliverPadding(padding: EdgeInsets.only(bottom: context.padding.bottom)),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@@ -34,6 +34,7 @@ class _UserInfoPageState extends LoadingState<UserInfoPage, UserDetails> {
|
||||
buildInformation(),
|
||||
SliverToBoxAdapter(child: buildHeader("Artworks"),),
|
||||
_UserArtworks(data.id.toString(), key: ValueKey(data.id),),
|
||||
SliverPadding(padding: EdgeInsets.only(bottom: context.padding.bottom)),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
Reference in New Issue
Block a user