mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-16 02:35:59 -07:00
fix: Improve keyboard input handling (#102)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
parent
2038847552
commit
76ac1aaa5b
7 changed files with 584 additions and 571 deletions
|
|
@ -16,6 +16,7 @@ import 'package:fladder/providers/user_provider.dart';
|
|||
import 'package:fladder/screens/shared/flat_button.dart';
|
||||
import 'package:fladder/screens/shared/input_fields.dart';
|
||||
import 'package:fladder/util/adaptive_layout.dart';
|
||||
import 'package:fladder/util/input_handler.dart';
|
||||
import 'package:fladder/util/list_padding.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:fladder/util/throttler.dart';
|
||||
|
|
@ -99,7 +100,7 @@ class _PhotoViewerControllsState extends ConsumerState<PhotoViewerControls> with
|
|||
timerController.playPause();
|
||||
return true;
|
||||
}
|
||||
if (value.logicalKey == LogicalKeyboardKey.keyF) {
|
||||
if (value.logicalKey == LogicalKeyboardKey.space) {
|
||||
widget.toggleOverlay?.call(null);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -117,12 +118,10 @@ class _PhotoViewerControllsState extends ConsumerState<PhotoViewerControls> with
|
|||
timerController.reset();
|
||||
},
|
||||
);
|
||||
ServicesBinding.instance.keyboard.addHandler(_onKey);
|
||||
}
|
||||
|
||||
@override
|
||||
void onWindowMinimize() {
|
||||
ServicesBinding.instance.keyboard.removeHandler(_onKey);
|
||||
timerController.cancel();
|
||||
super.onWindowMinimize();
|
||||
}
|
||||
|
|
@ -145,192 +144,197 @@ class _PhotoViewerControllsState extends ConsumerState<PhotoViewerControls> with
|
|||
|
||||
final padding = MediaQuery.of(context).padding;
|
||||
return PopScope(
|
||||
onPopInvokedWithResult: (didPop, result) async {
|
||||
await WakelockPlus.disable();
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
widthFactor: 1,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: gradient,
|
||||
onPopInvokedWithResult: (didPop, result) async => await WakelockPlus.disable(),
|
||||
child: InputHandler(
|
||||
onKeyEvent: (node, event) => _onKey(event) ? KeyEventResult.handled : KeyEventResult.ignored,
|
||||
child: Stack(
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
widthFactor: 1,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: gradient,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: widget.padding.top),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (AdaptiveLayout.of(context).isDesktop) const SizedBox(height: 25),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12)
|
||||
.add(EdgeInsets.only(left: padding.left, right: padding.right)),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
ElevatedIconButton(
|
||||
onPressed: () => Navigator.of(context).pop(widget.pageController.page?.toInt()),
|
||||
icon: getBackIcon(context),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Tooltip(
|
||||
message: widget.photo.name,
|
||||
child: Text(
|
||||
widget.photo.name,
|
||||
maxLines: 2,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium
|
||||
?.copyWith(fontWeight: FontWeight.bold, shadows: [
|
||||
BoxShadow(blurRadius: 1, spreadRadius: 1, color: Colors.black.withOpacity(0.7)),
|
||||
BoxShadow(blurRadius: 4, spreadRadius: 4, color: Colors.black.withOpacity(0.4)),
|
||||
BoxShadow(blurRadius: 20, spreadRadius: 6, color: Colors.black.withOpacity(0.2)),
|
||||
]),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: widget.padding.top),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (AdaptiveLayout.of(context).isDesktop) const SizedBox(height: 25),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12)
|
||||
.add(EdgeInsets.only(left: padding.left, right: padding.right)),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
ElevatedIconButton(
|
||||
onPressed: () => Navigator.of(context).pop(widget.pageController.page?.toInt()),
|
||||
icon: getBackIcon(context),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Tooltip(
|
||||
message: widget.photo.name,
|
||||
child: Text(
|
||||
widget.photo.name,
|
||||
maxLines: 2,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium
|
||||
?.copyWith(fontWeight: FontWeight.bold, shadows: [
|
||||
BoxShadow(blurRadius: 1, spreadRadius: 1, color: Colors.black.withOpacity(0.7)),
|
||||
BoxShadow(blurRadius: 4, spreadRadius: 4, color: Colors.black.withOpacity(0.4)),
|
||||
BoxShadow(blurRadius: 20, spreadRadius: 6, color: Colors.black.withOpacity(0.2)),
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
color: Theme.of(context).colorScheme.onPrimary),
|
||||
child: SquareProgressIndicator(
|
||||
value: widget.currentIndex / (widget.itemCount - 1),
|
||||
borderRadius: 7,
|
||||
clockwise: false,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
const SizedBox(width: 8),
|
||||
Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
color: Theme.of(context).colorScheme.onPrimary),
|
||||
child: SquareProgressIndicator(
|
||||
value: widget.currentIndex / (widget.itemCount - 1),
|
||||
borderRadius: 7,
|
||||
clockwise: false,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(9),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${widget.currentIndex + 1} / ${widget.loadingMoreItems ? "-" : "${widget.itemCount}"} ",
|
||||
style:
|
||||
Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
if (widget.loadingMoreItems)
|
||||
const SizedBox.square(
|
||||
dimension: 16,
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeCap: StrokeCap.round,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(9),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${widget.currentIndex + 1} / ${widget.loadingMoreItems ? "-" : "${widget.itemCount}"} ",
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium
|
||||
?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
].addInBetween(const SizedBox(width: 6)),
|
||||
if (widget.loadingMoreItems)
|
||||
const SizedBox.square(
|
||||
dimension: 16,
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeCap: StrokeCap.round,
|
||||
),
|
||||
),
|
||||
].addInBetween(const SizedBox(width: 6)),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned.fill(
|
||||
child: FlatButton(
|
||||
borderRadiusGeometry: BorderRadius.circular(8),
|
||||
onTap: () async {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => Dialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
child: SizedBox(
|
||||
width: 125,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
context.localized.goTo,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge
|
||||
?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
IntInputField(
|
||||
controller:
|
||||
TextEditingController(text: (widget.currentIndex + 1).toString()),
|
||||
onSubmitted: (value) {
|
||||
final position = ((value ?? 0) - 1).clamp(0, widget.itemCount - 1);
|
||||
widget.pageController.jumpToPage(position);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
Positioned.fill(
|
||||
child: FlatButton(
|
||||
borderRadiusGeometry: BorderRadius.circular(8),
|
||||
onTap: () async {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => Dialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
child: SizedBox(
|
||||
width: 125,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
context.localized.goTo,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge
|
||||
?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
IntInputField(
|
||||
controller: TextEditingController(
|
||||
text: (widget.currentIndex + 1).toString()),
|
||||
onSubmitted: (value) {
|
||||
final position =
|
||||
((value ?? 0) - 1).clamp(0, widget.itemCount - 1);
|
||||
widget.pageController.jumpToPage(position);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: gradient.reversed.toList(),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: gradient.reversed.toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
width: double.infinity,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(bottom: widget.padding.bottom),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0).add(EdgeInsets.only(left: padding.left, right: padding.right)),
|
||||
child: Row(
|
||||
children: [
|
||||
ElevatedIconButton(
|
||||
onPressed: widget.openOptions,
|
||||
icon: IconsaxOutline.more_2,
|
||||
),
|
||||
const Spacer(),
|
||||
ElevatedIconButton(
|
||||
onPressed: markAsFavourite,
|
||||
color: widget.photo.userData.isFavourite ? Colors.red : null,
|
||||
icon: widget.photo.userData.isFavourite ? IconsaxBold.heart : IconsaxOutline.heart,
|
||||
),
|
||||
ProgressFloatingButton(
|
||||
controller: timerController,
|
||||
onLongPress: (duration) {
|
||||
if (duration != null) {
|
||||
ref
|
||||
.read(photoViewSettingsProvider.notifier)
|
||||
.update((state) => state.copyWith(timer: duration));
|
||||
}
|
||||
},
|
||||
),
|
||||
].addPadding(const EdgeInsets.symmetric(horizontal: 8)),
|
||||
),
|
||||
)
|
||||
],
|
||||
width: double.infinity,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(bottom: widget.padding.bottom),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.all(8.0).add(EdgeInsets.only(left: padding.left, right: padding.right)),
|
||||
child: Row(
|
||||
children: [
|
||||
ElevatedIconButton(
|
||||
onPressed: widget.openOptions,
|
||||
icon: IconsaxOutline.more_2,
|
||||
),
|
||||
const Spacer(),
|
||||
ElevatedIconButton(
|
||||
onPressed: markAsFavourite,
|
||||
color: widget.photo.userData.isFavourite ? Colors.red : null,
|
||||
icon: widget.photo.userData.isFavourite ? IconsaxBold.heart : IconsaxOutline.heart,
|
||||
),
|
||||
ProgressFloatingButton(
|
||||
controller: timerController,
|
||||
onLongPress: (duration) {
|
||||
if (duration != null) {
|
||||
ref
|
||||
.read(photoViewSettingsProvider.notifier)
|
||||
.update((state) => state.copyWith(timer: duration));
|
||||
}
|
||||
},
|
||||
),
|
||||
].addPadding(const EdgeInsets.symmetric(horizontal: 8)),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue