mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 07:47:24 +00:00
improve ui
This commit is contained in:
@@ -296,7 +296,7 @@ class _FilledTabBarState extends State<FilledTabBar> {
|
||||
padding: tabPadding,
|
||||
radius: tabRadius,
|
||||
);
|
||||
if (old != null) {
|
||||
if (old != null && old.offsets != null && old.itemHeight != null) {
|
||||
painter!.update(old.offsets!, old.itemHeight!);
|
||||
}
|
||||
}
|
||||
|
@@ -262,6 +262,8 @@ class ContentDialog extends StatelessWidget {
|
||||
insetPadding: context.width < 400
|
||||
? const EdgeInsets.symmetric(horizontal: 4)
|
||||
: const EdgeInsets.symmetric(horizontal: 16),
|
||||
elevation: 2,
|
||||
shadowColor: context.colorScheme.shadow,
|
||||
child: IntrinsicWidth(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
|
@@ -127,15 +127,15 @@ class _NaviPaneState extends State<NaviPane>
|
||||
}
|
||||
if (target == 1) {
|
||||
StateController.find<NaviPaddingWidgetController>()
|
||||
.setWithPadding(true, true);
|
||||
.setWithPadding(true, true, true);
|
||||
controller.value = target;
|
||||
} else if (controller.value == 1 && target == 0) {
|
||||
StateController.findOrNull<NaviPaddingWidgetController>()
|
||||
?.setWithPadding(false, false);
|
||||
?.setWithPadding(false, false, false);
|
||||
controller.value = target;
|
||||
} else {
|
||||
StateController.findOrNull<NaviPaddingWidgetController>()
|
||||
?.setWithPadding(true, false);
|
||||
?.setWithPadding(true, false, false);
|
||||
controller.animateTo(target);
|
||||
}
|
||||
animationTarget = target;
|
||||
@@ -660,9 +660,13 @@ class NaviPaddingWidgetController extends StateController {
|
||||
|
||||
bool _withTopBarPadding = false;
|
||||
|
||||
void setWithPadding(bool withPadding, bool withAppbarPadding) {
|
||||
bool _withBottomBarPadding = false;
|
||||
|
||||
void setWithPadding(
|
||||
bool withPadding, bool withAppbarPadding, bool withBottomBarPadding) {
|
||||
_withPadding = withPadding;
|
||||
_withTopBarPadding = withAppbarPadding;
|
||||
_withBottomBarPadding = withBottomBarPadding;
|
||||
update();
|
||||
}
|
||||
}
|
||||
@@ -683,8 +687,10 @@ class NaviPaddingWidget extends StatelessWidget {
|
||||
(controller._withTopBarPadding
|
||||
? _NaviPaneState._kTopBarHeight
|
||||
: 0),
|
||||
bottom:
|
||||
_NaviPaneState._kBottomBarHeight + context.padding.bottom,
|
||||
bottom: context.padding.bottom +
|
||||
(controller._withBottomBarPadding
|
||||
? _NaviPaneState._kBottomBarHeight
|
||||
: 0),
|
||||
)
|
||||
: EdgeInsets.zero,
|
||||
child: child,
|
||||
|
@@ -55,7 +55,7 @@ class _SmoothScrollProviderState extends State<SmoothScrollProvider> {
|
||||
return widget.builder(
|
||||
context,
|
||||
_controller,
|
||||
const ClampingScrollPhysics(),
|
||||
const BouncingScrollPhysics(),
|
||||
);
|
||||
}
|
||||
return Listener(
|
||||
@@ -93,7 +93,7 @@ class _SmoothScrollProviderState extends State<SmoothScrollProvider> {
|
||||
_controller,
|
||||
_isMouseScroll
|
||||
? const NeverScrollableScrollPhysics()
|
||||
: const ClampingScrollPhysics(),
|
||||
: const BouncingScrollPhysics(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@@ -51,9 +51,9 @@ class _Appdata {
|
||||
return;
|
||||
}
|
||||
var json = jsonDecode(await file.readAsString());
|
||||
for(var key in json['settings'].keys) {
|
||||
if(json[key] != null) {
|
||||
settings[key] = json[key];
|
||||
for(var key in (json['settings'] as Map<String, dynamic>).keys) {
|
||||
if(json['settings'][key] != null) {
|
||||
settings[key] = json['settings'][key];
|
||||
}
|
||||
}
|
||||
searchHistory = List.from(json['searchHistory']);
|
||||
|
@@ -56,6 +56,7 @@ class _MyAppState extends State<MyApp> {
|
||||
@override
|
||||
void initState() {
|
||||
App.registerForceRebuild(forceRebuild);
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
@@ -74,6 +74,7 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
||||
buildChapters(),
|
||||
buildThumbnails(),
|
||||
buildRecommend(),
|
||||
SliverPadding(padding: EdgeInsets.only(bottom: context.padding.bottom)),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -109,6 +110,8 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
|
||||
],
|
||||
);
|
||||
|
||||
yield const SliverPadding(padding: EdgeInsets.only(top: 8));
|
||||
|
||||
yield Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
@@ -243,7 +243,7 @@ class _BodyState extends State<_Body> {
|
||||
.paddingBottom(32),
|
||||
Row(
|
||||
children: [
|
||||
TextButton(onPressed: chooseFile, child: Text("Choose file".tl))
|
||||
TextButton(onPressed: selectFile, child: Text("Select file".tl))
|
||||
.paddingLeft(8),
|
||||
const Spacer(),
|
||||
TextButton(
|
||||
@@ -265,7 +265,7 @@ class _BodyState extends State<_Body> {
|
||||
);
|
||||
}
|
||||
|
||||
void chooseFile() async {
|
||||
void selectFile() async {
|
||||
final result = await FilePicker.platform.pickFiles(
|
||||
type: FileType.custom,
|
||||
allowedExtensions: ['js'],
|
||||
|
@@ -260,7 +260,8 @@ class _ComicImageState extends State<ComicImage> with WidgetsBindingObserver {
|
||||
if (_lastException != null) {
|
||||
// display error and retry button on screen
|
||||
return SizedBox(
|
||||
height: 300,
|
||||
height: widget.height == null ? 300 : null,
|
||||
width: widget.width == null ? 300 : null,
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
height: 300,
|
||||
@@ -295,87 +296,92 @@ class _ComicImageState extends State<ComicImage> with WidgetsBindingObserver {
|
||||
);
|
||||
}
|
||||
|
||||
var width = widget.width??MediaQuery.of(context).size.width;
|
||||
double? height;
|
||||
return LayoutBuilder(builder: (context, constrains) {
|
||||
var width = widget.width;
|
||||
var height = widget.height;
|
||||
|
||||
Size? cacheSize = _cache[widget.image.hashCode];
|
||||
if(cacheSize != null){
|
||||
height = cacheSize.height * (width / cacheSize.width);
|
||||
height = height.ceilToDouble();
|
||||
}
|
||||
|
||||
var brightness = Theme.of(context).brightness;
|
||||
|
||||
if(_imageInfo != null){
|
||||
// Record the height and the width of the image
|
||||
_cache[widget.image.hashCode] = Size(
|
||||
_imageInfo!.image.width.toDouble(),
|
||||
_imageInfo!.image.height.toDouble()
|
||||
);
|
||||
// build image
|
||||
Widget result = RawImage(
|
||||
// Do not clone the image, because RawImage is a stateless wrapper.
|
||||
// The image will be disposed by this state object when it is not needed
|
||||
// anymore, such as when it is unmounted or when the image stream pushes
|
||||
// a new image.
|
||||
image: _imageInfo?.image,
|
||||
debugImageLabel: _imageInfo?.debugLabel,
|
||||
width: width,
|
||||
height: height,
|
||||
scale: _imageInfo?.scale ?? 1.0,
|
||||
color: widget.color,
|
||||
opacity: widget.opacity,
|
||||
colorBlendMode: widget.colorBlendMode,
|
||||
fit: widget.fit,
|
||||
alignment: widget.alignment,
|
||||
repeat: widget.repeat,
|
||||
centerSlice: widget.centerSlice,
|
||||
matchTextDirection: widget.matchTextDirection,
|
||||
invertColors: _invertColors,
|
||||
isAntiAlias: widget.isAntiAlias,
|
||||
filterQuality: widget.filterQuality,
|
||||
);
|
||||
|
||||
if (!widget.excludeFromSemantics) {
|
||||
result = Semantics(
|
||||
container: widget.semanticLabel != null,
|
||||
image: true,
|
||||
label: widget.semanticLabel ?? '',
|
||||
child: result,
|
||||
if(_imageInfo != null) {
|
||||
// Record the height and the width of the image
|
||||
_cache[widget.image.hashCode] = Size(
|
||||
_imageInfo!.image.width.toDouble(),
|
||||
_imageInfo!.image.height.toDouble()
|
||||
);
|
||||
}
|
||||
result = SizedBox(
|
||||
width: width,
|
||||
height: height,
|
||||
child: Center(
|
||||
child: result,
|
||||
),
|
||||
);
|
||||
return result;
|
||||
} else {
|
||||
// build progress
|
||||
return SizedBox(
|
||||
width: width,
|
||||
height: height??300,
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(
|
||||
backgroundColor: brightness == Brightness.dark
|
||||
? Colors.white24
|
||||
: Colors.black12,
|
||||
strokeWidth: 3,
|
||||
value: (_loadingProgress != null &&
|
||||
_loadingProgress!.expectedTotalBytes!=null &&
|
||||
_loadingProgress!.expectedTotalBytes! != 0)
|
||||
?_loadingProgress!.cumulativeBytesLoaded / _loadingProgress!.expectedTotalBytes!
|
||||
:0,
|
||||
|
||||
Size? cacheSize = _cache[widget.image.hashCode];
|
||||
if(cacheSize != null){
|
||||
if(width == double.infinity) {
|
||||
width = constrains.maxWidth;
|
||||
height = width * cacheSize.height / cacheSize.width;
|
||||
} else if(height == double.infinity) {
|
||||
height = constrains.maxHeight;
|
||||
width = height * cacheSize.width / cacheSize.height;
|
||||
}
|
||||
}
|
||||
|
||||
if(_imageInfo != null){
|
||||
// build image
|
||||
Widget result = RawImage(
|
||||
// Do not clone the image, because RawImage is a stateless wrapper.
|
||||
// The image will be disposed by this state object when it is not needed
|
||||
// anymore, such as when it is unmounted or when the image stream pushes
|
||||
// a new image.
|
||||
image: _imageInfo?.image,
|
||||
debugImageLabel: _imageInfo?.debugLabel,
|
||||
width: width,
|
||||
height: height,
|
||||
scale: _imageInfo?.scale ?? 1.0,
|
||||
color: widget.color,
|
||||
opacity: widget.opacity,
|
||||
colorBlendMode: widget.colorBlendMode,
|
||||
fit: widget.fit,
|
||||
alignment: widget.alignment,
|
||||
repeat: widget.repeat,
|
||||
centerSlice: widget.centerSlice,
|
||||
matchTextDirection: widget.matchTextDirection,
|
||||
invertColors: _invertColors,
|
||||
isAntiAlias: widget.isAntiAlias,
|
||||
filterQuality: widget.filterQuality,
|
||||
);
|
||||
|
||||
if (!widget.excludeFromSemantics) {
|
||||
result = Semantics(
|
||||
container: widget.semanticLabel != null,
|
||||
image: true,
|
||||
label: widget.semanticLabel ?? '',
|
||||
child: result,
|
||||
);
|
||||
}
|
||||
result = SizedBox(
|
||||
width: width,
|
||||
height: height,
|
||||
child: Center(
|
||||
child: result,
|
||||
),
|
||||
);
|
||||
return result;
|
||||
} else {
|
||||
// build progress
|
||||
return SizedBox(
|
||||
width: width,
|
||||
height: height,
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 3,
|
||||
value: (_loadingProgress != null &&
|
||||
_loadingProgress!.expectedTotalBytes!=null &&
|
||||
_loadingProgress!.expectedTotalBytes! != 0)
|
||||
?_loadingProgress!.cumulativeBytesLoaded / _loadingProgress!.expectedTotalBytes!
|
||||
:0,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
@@ -258,7 +258,7 @@ class _GalleryModeState extends State<_GalleryMode>
|
||||
event.logicalKey == LogicalKeyboardKey.arrowRight) {
|
||||
forward = false;
|
||||
}
|
||||
if(event is KeyDownEvent || event is KeyRepeatEvent) {
|
||||
if (event is KeyDownEvent || event is KeyRepeatEvent) {
|
||||
if (forward == true) {
|
||||
controller.nextPage(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
@@ -371,13 +371,12 @@ class _ContinuousModeState extends State<_ContinuousMode>
|
||||
if (index == 0 || index == reader.maxPage + 1) {
|
||||
return const SizedBox();
|
||||
}
|
||||
double width = MediaQuery.of(context).size.width;
|
||||
double height = MediaQuery.of(context).size.height;
|
||||
|
||||
double imageWidth = width;
|
||||
|
||||
if (height / width < 1.2) {
|
||||
imageWidth = height / 1.2;
|
||||
double? width, height;
|
||||
if (reader.mode == ReaderMode.continuousLeftToRight ||
|
||||
reader.mode == ReaderMode.continuousRightToLeft) {
|
||||
height = double.infinity;
|
||||
} else {
|
||||
width = double.infinity;
|
||||
}
|
||||
|
||||
_precacheImage(index, context);
|
||||
@@ -387,9 +386,9 @@ class _ContinuousModeState extends State<_ContinuousMode>
|
||||
return ComicImage(
|
||||
filterQuality: FilterQuality.medium,
|
||||
image: image,
|
||||
width: imageWidth,
|
||||
height: imageWidth * 1.2,
|
||||
fit: BoxFit.cover,
|
||||
width: width,
|
||||
height: height,
|
||||
fit: BoxFit.contain,
|
||||
);
|
||||
},
|
||||
scrollBehavior: const MaterialScrollBehavior()
|
||||
@@ -420,10 +419,10 @@ class _ContinuousModeState extends State<_ContinuousMode>
|
||||
return;
|
||||
}
|
||||
if (scrollController.offset !=
|
||||
scrollController.position.maxScrollExtent &&
|
||||
scrollController.position.maxScrollExtent &&
|
||||
scrollController.offset !=
|
||||
scrollController.position.minScrollExtent) {
|
||||
if(reader.mode == ReaderMode.continuousTopToBottom) {
|
||||
if (reader.mode == ReaderMode.continuousTopToBottom) {
|
||||
value = Offset(value.dx, 0);
|
||||
} else {
|
||||
value = Offset(0, value.dy);
|
||||
|
@@ -102,7 +102,9 @@ class _ReaderState extends State<Reader> with _ReaderLocation, _ReaderWindow {
|
||||
chapter = widget.initialChapter ?? 1;
|
||||
mode = ReaderMode.fromKey(appdata.settings['readerMode']);
|
||||
history = widget.history;
|
||||
updateHistory();
|
||||
Future.microtask(() {
|
||||
updateHistory();
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user