feat(legacy-ui): add animated transitions for dialogs and navigation

This commit is contained in:
2026-04-26 05:11:42 +02:00
parent 309c7b1d87
commit d9465996d7
19 changed files with 114 additions and 51 deletions

View File

@@ -100,7 +100,7 @@ class AccountSettingsScreen extends ConsumerWidget {
_item(
context,
onPressed: () {
showDialog<void>(
showLegacyDialog<void>(
context: context,
builder: (_) => Dialog(
backgroundColor: Colors.transparent,

View File

@@ -128,7 +128,7 @@ class AppUserCard extends ConsumerWidget {
),
child: IconButton(
onPressed: () {
showDialog(
showLegacyDialog(
context: context,
builder: (context) => Dialog(
child: Container(

View File

@@ -141,7 +141,7 @@ class _RequestCancelSection extends ConsumerWidget {
}
if (!context.mounted) return;
showDialog<void>(
showLegacyDialog<void>(
context: context,
builder: (_) => ConfirmDialog(navigationContract: navigationContract),
);

View File

@@ -129,7 +129,7 @@ class _LinkedDeviceCard extends StatelessWidget {
borderRadius: const BorderRadius.all(Radius.circular(12)),
),
child: IconButton(
onPressed: () => showDialog<void>(
onPressed: () => showLegacyDialog<void>(
context: context,
builder: (_) => Dialog(child: DeleteDeviceDialog(device: device)),
),
@@ -145,7 +145,7 @@ class _LinkedDeviceCard extends StatelessWidget {
child: IconButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute<void>(
LegacyPageRoute<void>(
builder: (_) => EditLinkedDeviceScreen(device: device),
),
),

View File

@@ -76,7 +76,7 @@ class CustomerServiceScreen extends ConsumerWidget {
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
LegacyPageRoute(
builder: (_) =>
ContactScreen(navigationContract: navigationContract),
),

View File

@@ -21,14 +21,16 @@ class BackgroundImageScreen extends ConsumerWidget {
final primaryColor = context.sfColors.legacyPrimary;
final device = ref.watch(selectedDeviceProvider).value;
final photosAsync = ref.watch(backgroundImagePhotosProvider);
final isSaving = ref
.watch(backgroundImageControllerProvider.select((s) => s.isLoading));
final isSaving = ref.watch(
backgroundImageControllerProvider.select((s) => s.isLoading),
);
ref.listen(backgroundImageControllerProvider, (prev, next) async {
if (prev == null || !prev.isLoading || next.isLoading) return;
if (next.hasError) {
final action =
ref.read(backgroundImageControllerProvider.notifier).lastAction;
final action = ref
.read(backgroundImageControllerProvider.notifier)
.lastAction;
final key = switch (action) {
BackgroundImageAction.uploaded => I18n.errorBackgroundImageUpload,
BackgroundImageAction.backgroundSet => I18n.errorBackgroundImageSet,
@@ -37,8 +39,9 @@ class BackgroundImageScreen extends ConsumerWidget {
await showErrorDialog(context, key);
return;
}
final action =
ref.read(backgroundImageControllerProvider.notifier).lastAction;
final action = ref
.read(backgroundImageControllerProvider.notifier)
.lastAction;
final key = switch (action) {
BackgroundImageAction.uploaded => I18n.backgroundImageUploaded,
BackgroundImageAction.backgroundSet => I18n.backgroundImageSet,
@@ -64,7 +67,7 @@ class BackgroundImageScreen extends ConsumerWidget {
),
),
title: Text(
context.translate(I18n.customBackground).toUpperCase(),
context.translate(I18n.customBackground),
style: TextStyle(
fontSize: SizeUtils.getByScreen(small: 20, big: 19),
fontWeight: FontWeight.w500,
@@ -242,8 +245,7 @@ class _PhotoGrid extends StatelessWidget {
child: Icon(
Icons.image_outlined,
size: 48,
color:
Theme.of(context).colorScheme.outline,
color: Theme.of(context).colorScheme.outline,
),
),
),

View File

@@ -56,7 +56,7 @@ class LocateDeviceScreen extends ConsumerWidget {
),
child: PrimaryButton(
onPressed: () {
showDialog<void>(
showLegacyDialog<void>(
context: context,
builder: (_) => const Dialog(child: LocateDeviceDialog()),
);

View File

@@ -1,3 +1,4 @@
import 'package:legacy_ui/legacy_ui.dart';
import 'package:design_system/design_system.dart';
import 'package:device_management/src/features/scheduled_activities/domain/entities/scheduled_activity_entity.dart';
import 'package:device_management/src/features/scheduled_activities/presentation/providers/scheduled_activities_controller.dart';
@@ -197,7 +198,7 @@ class _ActivityTimelineCard extends ConsumerWidget {
onPressed: () async {
if (!await guardDeviceCommand(context, ref)) return;
if (!context.mounted) return;
final confirmed = await showDialog<bool>(
final confirmed = await showLegacyDialog<bool>(
context: context,
builder: (dialogContext) => AlertDialog(
title: Text(

View File

@@ -1,9 +1,10 @@
import 'package:legacy_ui/legacy_ui.dart';
import 'package:flutter/material.dart';
import 'package:sf_localizations/sf_localizations.dart';
import 'package:utils/utils.dart';
void showActivationCodeDialog(BuildContext context) {
showDialog(
showLegacyDialog(
context: context,
builder: (context) => Dialog(
shape: RoundedRectangleBorder(

View File

@@ -1,3 +1,4 @@
import 'package:legacy_ui/legacy_ui.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -119,7 +120,7 @@ class _LegacyRequestRecoveryScreenState
if (updated.recoveryRequested) {
Navigator.push(
context,
MaterialPageRoute(
LegacyPageRoute(
builder: (_) => LegacySentScreen(
navigationContract:
widget.navigationContract,

View File

@@ -1,3 +1,4 @@
import 'package:legacy_ui/legacy_ui.dart';
import 'package:legacy_auth/src/features/recover_password/presentation/new_password/new_password_screen.dart';
import 'package:legacy_theme/legacy_theme.dart';
import 'package:design_system/design_system.dart';
@@ -99,7 +100,7 @@ class LegacySentScreen extends ConsumerWidget {
child: PrimaryButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
LegacyPageRoute(
builder: (_) => LegacyNewPasswordScreen(
navigationContract: navigationContract,
),

View File

@@ -31,6 +31,8 @@ dependencies:
path: ../../../../packages/sf_tracking
legacy_device_state:
path: ../../packages/legacy_device_state
legacy_ui:
path: ../../packages/legacy_ui
fonts:
path: ../../../../packages/fonts
#dependencies go here
@@ -47,6 +49,7 @@ dependencies:
json_serializable: ^6.11.2
uuid: ^4.5.3
mobile_scanner: ^7.1.4
url_launcher: ^6.3.1
dio_cookie_manager: ^3.3.0
cookie_jar: ^4.0.8
path_provider: ^2.1.5

View File

@@ -1,3 +1,4 @@
import 'package:legacy_ui/legacy_ui.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -26,10 +27,7 @@ class AlarmScreen extends ConsumerWidget {
ref.listen(alarmControllerProvider, (prev, next) {
next.showErrorOn(context);
if (prev != null &&
prev.isLoading &&
!next.isLoading &&
!next.hasError) {
if (prev != null && prev.isLoading && !next.isLoading && !next.hasError) {
ref.read(alarmsEditorProvider.notifier).clear();
}
});
@@ -85,11 +83,7 @@ class AlarmScreen extends ConsumerWidget {
return;
}
if (!context.mounted) return;
_openForm(
context,
ref,
fetchedAlarms: fetchedAlarms,
);
_openForm(context, ref, fetchedAlarms: fetchedAlarms);
},
icon: Icon(
Icons.add,
@@ -130,8 +124,10 @@ class AlarmScreen extends ConsumerWidget {
),
bottomNavigationBar: alarms.isNotEmpty
? Padding(
padding:
const EdgeInsets.symmetric(horizontal: 24, vertical: 10),
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 10,
),
child: isSaving
? const Center(child: CircularProgressIndicator())
: PrimaryButton(
@@ -142,13 +138,9 @@ class AlarmScreen extends ConsumerWidget {
.read(alarmControllerProvider.notifier)
.save(deviceId: device.id, alarms: alarms);
if (!context.mounted) return;
final state =
ref.read(alarmControllerProvider);
final state = ref.read(alarmControllerProvider);
if (state.hasError) return;
await showSuccessDialog(
context,
I18n.alarmSaved,
);
await showSuccessDialog(context, I18n.alarmSaved);
},
text: context.translate(I18n.alarmSave),
color: primaryColor,
@@ -181,7 +173,7 @@ class AlarmScreen extends ConsumerWidget {
),
),
title: Text(
context.translate(I18n.alarm).toUpperCase(),
context.translate(I18n.alarm),
style: TextStyle(
fontSize: SizeUtils.getByScreen(small: 20, big: 19),
fontWeight: FontWeight.w500,
@@ -203,7 +195,7 @@ class AlarmScreen extends ConsumerWidget {
Future<bool?> _confirmDelete(BuildContext context) {
final theme = Theme.of(context);
return showDialog<bool>(
return showLegacyDialog<bool>(
context: context,
builder: (dialogContext) => AlertDialog(
icon: Icon(
@@ -243,11 +235,7 @@ class AlarmScreen extends ConsumerWidget {
onSave: (result) {
final editor = ref.read(alarmsEditorProvider.notifier);
if (index != null) {
editor.replace(
current: fetchedAlarms,
index: index,
alarm: result,
);
editor.replace(current: fetchedAlarms, index: index, alarm: result);
} else {
editor.add(current: fetchedAlarms, alarm: result);
}

View File

@@ -1,3 +1,4 @@
import 'package:legacy_ui/legacy_ui.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -137,7 +138,7 @@ class BlockPhoneScreen extends ConsumerWidget {
),
),
title: Text(
context.translate(I18n.blockPhone).toUpperCase(),
context.translate(I18n.blockPhone),
style: TextStyle(
fontSize: SizeUtils.getByScreen(small: 20, big: 19),
fontWeight: FontWeight.w500,
@@ -172,7 +173,7 @@ class BlockPhoneScreen extends ConsumerWidget {
Future<bool?> _confirmDelete(BuildContext context, String name) {
final theme = Theme.of(context);
return showDialog<bool>(
return showLegacyDialog<bool>(
context: context,
builder: (dialogContext) => AlertDialog(
icon: Icon(
@@ -282,8 +283,7 @@ class _ContactList extends StatelessWidget {
context.translate(I18n.whitelistDescription),
style: TextStyle(
fontSize: SizeUtils.getByScreen(small: 14, big: 15),
color:
Theme.of(context).colorScheme.onSurface.withAlpha(178),
color: Theme.of(context).colorScheme.onSurface.withAlpha(178),
),
),
),

View File

@@ -34,7 +34,7 @@ class RemoteManagementScreen extends ConsumerWidget {
}) async {
if (!await guardDeviceCommand(context, ref)) return;
if (!context.mounted) return;
await showDialog<void>(
await showLegacyDialog<void>(
context: context,
builder: (_) => ConfirmDialog(
title: title,

View File

@@ -1,3 +1,4 @@
import 'package:legacy_ui/legacy_ui.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -347,7 +348,7 @@ class _Body extends ConsumerWidget {
if (!context.mounted) return;
final primaryColor = context.sfColors.legacyPrimary;
showDialog<void>(
showLegacyDialog<void>(
context: context,
builder: (dialogContext) => AlertDialog(
title: Text(context.translate(I18n.removeWifiNetwork)),

View File

@@ -5,3 +5,4 @@ export 'src/widgets/pulsing_location_marker.dart';
export 'src/widgets/refreshable_error_state.dart';
export 'src/widgets/week_day_chips.dart';
export 'src/providers/map_style_provider.dart';
export 'src/transitions/legacy_transitions.dart';

View File

@@ -0,0 +1,64 @@
import 'package:flutter/material.dart';
const _duration = Duration(milliseconds: 300);
const _dialogDuration = Duration(milliseconds: 500);
Future<T?> showLegacyDialog<T>({
required BuildContext context,
required WidgetBuilder builder,
bool barrierDismissible = true,
}) {
return showGeneralDialog<T>(
context: context,
barrierDismissible: barrierDismissible,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
barrierColor: Colors.black54,
transitionDuration: _dialogDuration,
pageBuilder: (dialogContext, __, ___) => builder(dialogContext),
transitionBuilder: (_, animation, __, child) {
final fadeCurved = CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
reverseCurve: Curves.easeIn,
);
final scaleCurved = CurvedAnimation(
parent: animation,
curve: Curves.easeOutBack,
reverseCurve: Curves.easeInCubic,
);
return FadeTransition(
opacity: fadeCurved,
child: ScaleTransition(
scale: Tween<double>(begin: 0.6, end: 1.0).animate(scaleCurved),
child: child,
),
);
},
);
}
class LegacyPageRoute<T> extends PageRouteBuilder<T> {
LegacyPageRoute({required WidgetBuilder builder})
: super(
transitionDuration: _duration,
reverseTransitionDuration: _duration,
pageBuilder: (context, _, __) => builder(context),
transitionsBuilder: (_, animation, __, child) {
final curved = CurvedAnimation(
parent: animation,
curve: Curves.easeOutCubic,
reverseCurve: Curves.easeInCubic,
);
return FadeTransition(
opacity: curved,
child: SlideTransition(
position: Tween<Offset>(
begin: const Offset(1, 0),
end: Offset.zero,
).animate(curved),
child: child,
),
);
},
);
}

View File

@@ -46,7 +46,7 @@ class LegacyPageLayout extends StatelessWidget {
)
: null,
title: Text(
title.toUpperCase(),
title,
style: TextStyle(
fontSize: SizeUtils.getByScreen(small: 20, big: 19),
fontWeight: FontWeight.w500,