mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-07 09:15:49 -06:00
Bugfixes, finished filter rework
This commit is contained in:
@@ -1,15 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ComingSoon extends StatelessWidget {
|
||||
const ComingSoon({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Text(
|
||||
"Coming Soon\u2122",
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ElevatedConfirmationButton extends StatefulWidget {
|
||||
factory ElevatedConfirmationButton.icon(BuildContext context,
|
||||
{required void Function() onPressed,
|
||||
required Icon icon,
|
||||
required Widget label}) {
|
||||
final double scale = MediaQuery.maybeOf(context)?.textScaleFactor ?? 1;
|
||||
final double gap =
|
||||
scale <= 1 ? 8 : lerpDouble(8, 4, math.min(scale - 1, 1))!;
|
||||
return ElevatedConfirmationButton(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[icon, SizedBox(width: gap), Flexible(child: label)],
|
||||
),
|
||||
onPressed: onPressed,
|
||||
);
|
||||
}
|
||||
|
||||
const ElevatedConfirmationButton({
|
||||
Key? key,
|
||||
this.color,
|
||||
required this.onPressed,
|
||||
required this.child,
|
||||
this.confirmWidget = const Text("Confirm?"),
|
||||
}) : super(key: key);
|
||||
|
||||
final Color? color;
|
||||
final void Function()? onPressed;
|
||||
final Widget child;
|
||||
final Widget confirmWidget;
|
||||
@override
|
||||
State<ElevatedConfirmationButton> createState() =>
|
||||
_ElevatedConfirmationButtonState();
|
||||
}
|
||||
|
||||
class _ElevatedConfirmationButtonState
|
||||
extends State<ElevatedConfirmationButton> {
|
||||
bool _clickedOnce = false;
|
||||
double? _originalWidth;
|
||||
final GlobalKey _originalWidgetKey = GlobalKey();
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (!_clickedOnce) {
|
||||
return ElevatedButton(
|
||||
key: _originalWidgetKey,
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all(widget.color),
|
||||
),
|
||||
onPressed: () {
|
||||
_originalWidth = (_originalWidgetKey.currentContext
|
||||
?.findRenderObject() as RenderBox)
|
||||
.size
|
||||
.width;
|
||||
setState(() => _clickedOnce = true);
|
||||
},
|
||||
child: widget.child,
|
||||
);
|
||||
} else {
|
||||
return Builder(builder: (context) {
|
||||
return SizedBox(
|
||||
width: _originalWidth,
|
||||
child: ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all(widget.color),
|
||||
),
|
||||
onPressed: widget.onPressed,
|
||||
child: widget.confirmWidget,
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,215 +0,0 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@immutable
|
||||
class ExpandableFloatingActionButton extends StatefulWidget {
|
||||
const ExpandableFloatingActionButton({
|
||||
super.key,
|
||||
this.initialOpen,
|
||||
required this.distance,
|
||||
required this.children,
|
||||
});
|
||||
|
||||
final bool? initialOpen;
|
||||
final double distance;
|
||||
final List<Widget> children;
|
||||
|
||||
@override
|
||||
State<ExpandableFloatingActionButton> createState() =>
|
||||
_ExpandableFloatingActionButtonState();
|
||||
}
|
||||
|
||||
class _ExpandableFloatingActionButtonState
|
||||
extends State<ExpandableFloatingActionButton>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late final AnimationController _controller;
|
||||
late final Animation<double> _expandAnimation;
|
||||
bool _open = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_open = widget.initialOpen ?? false;
|
||||
_controller = AnimationController(
|
||||
value: _open ? 1.0 : 0.0,
|
||||
duration: const Duration(milliseconds: 250),
|
||||
vsync: this,
|
||||
);
|
||||
_expandAnimation = CurvedAnimation(
|
||||
curve: Curves.fastOutSlowIn,
|
||||
reverseCurve: Curves.easeOutQuad,
|
||||
parent: _controller,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _toggle() {
|
||||
setState(() {
|
||||
_open = !_open;
|
||||
if (_open) {
|
||||
_controller.forward();
|
||||
} else {
|
||||
_controller.reverse();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox.expand(
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomRight,
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
_buildTapToCloseFab(),
|
||||
..._buildExpandingActionButtons(),
|
||||
_buildTapToOpenFab(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTapToCloseFab() {
|
||||
return SizedBox(
|
||||
width: 56.0,
|
||||
height: 56.0,
|
||||
child: Center(
|
||||
child: Material(
|
||||
shape: const CircleBorder(),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
elevation: 4.0,
|
||||
child: InkWell(
|
||||
onTap: _toggle,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _buildExpandingActionButtons() {
|
||||
final children = <Widget>[];
|
||||
final count = widget.children.length;
|
||||
final step = 90.0 / (count - 1);
|
||||
for (var i = 0, angleInDegrees = 0.0;
|
||||
i < count;
|
||||
i++, angleInDegrees += step) {
|
||||
children.add(
|
||||
_ExpandingActionButton(
|
||||
directionInDegrees: angleInDegrees,
|
||||
maxDistance: widget.distance,
|
||||
progress: _expandAnimation,
|
||||
child: widget.children[i],
|
||||
),
|
||||
);
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
Widget _buildTapToOpenFab() {
|
||||
return IgnorePointer(
|
||||
ignoring: _open,
|
||||
child: AnimatedContainer(
|
||||
transformAlignment: Alignment.center,
|
||||
transform: Matrix4.diagonal3Values(
|
||||
_open ? 0.7 : 1.0,
|
||||
_open ? 0.7 : 1.0,
|
||||
1.0,
|
||||
),
|
||||
duration: const Duration(milliseconds: 250),
|
||||
curve: const Interval(0.0, 0.5, curve: Curves.easeOut),
|
||||
child: AnimatedOpacity(
|
||||
opacity: _open ? 0.0 : 1.0,
|
||||
curve: const Interval(0.25, 1.0, curve: Curves.easeInOut),
|
||||
duration: const Duration(milliseconds: 250),
|
||||
child: FloatingActionButton(
|
||||
onPressed: _toggle,
|
||||
child: const Icon(Icons.create),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@immutable
|
||||
class _ExpandingActionButton extends StatelessWidget {
|
||||
const _ExpandingActionButton({
|
||||
required this.directionInDegrees,
|
||||
required this.maxDistance,
|
||||
required this.progress,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
final double directionInDegrees;
|
||||
final double maxDistance;
|
||||
final Animation<double> progress;
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: progress,
|
||||
builder: (context, child) {
|
||||
final offset = Offset.fromDirection(
|
||||
directionInDegrees * (math.pi / 180.0),
|
||||
progress.value * maxDistance,
|
||||
);
|
||||
return Positioned(
|
||||
right: 4.0 + offset.dx,
|
||||
bottom: 4.0 + offset.dy,
|
||||
child: Transform.rotate(
|
||||
angle: (1.0 - progress.value) * math.pi / 2,
|
||||
child: child!,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: FadeTransition(
|
||||
opacity: progress,
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@immutable
|
||||
class ExpandableActionButton extends StatelessWidget {
|
||||
const ExpandableActionButton({
|
||||
super.key,
|
||||
this.color,
|
||||
this.onPressed,
|
||||
required this.icon,
|
||||
});
|
||||
|
||||
final VoidCallback? onPressed;
|
||||
final Widget icon;
|
||||
final Color? color;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 48,
|
||||
width: 48,
|
||||
child: ElevatedButton(
|
||||
onPressed: onPressed,
|
||||
child: icon,
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.all(EdgeInsets.zero),
|
||||
backgroundColor: MaterialStateProperty.all(color),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,20 +6,26 @@ class OfflineBanner extends StatelessWidget with PreferredSizeWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Theme.of(context).disabledColor,
|
||||
return ColoredBox(
|
||||
color: Theme.of(context).colorScheme.errorContainer,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Padding(
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: Icon(
|
||||
Icons.cloud_off,
|
||||
size: 24,
|
||||
color: Theme.of(context).colorScheme.onErrorContainer,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
S.of(context).genericMessageOfflineText,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onErrorContainer,
|
||||
),
|
||||
),
|
||||
Text(S.of(context).genericMessageOfflineText),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user