diff --git a/assets/fonts/RobotoMono-VariableFont_wght.ttf b/assets/fonts/RobotoMono-VariableFont_wght.ttf new file mode 100644 index 00000000..fc02de43 Binary files /dev/null and b/assets/fonts/RobotoMono-VariableFont_wght.ttf differ diff --git a/lib/ui/atoms/list_tiles/quota_selection_tile.dart b/lib/ui/atoms/list_tiles/quota_selection_tile.dart new file mode 100644 index 00000000..6099f4d4 --- /dev/null +++ b/lib/ui/atoms/list_tiles/quota_selection_tile.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; + +class QuotaSelectionTile extends StatelessWidget { + const QuotaSelectionTile({ + required this.title, + required this.subtitle, + required this.value, + required this.min, + required this.max, + required this.callback, + super.key, + }); + + final String title; + final String subtitle; + final int value; + final int min; + final int max; + final void Function(double) callback; + + @override + Widget build(final BuildContext context) => ExpansionTile( + title: Text(title), + subtitle: Text(subtitle), + trailing: Text( + value == -1 ? '∞' : value.toString(), + style: Theme.of(context).textTheme.headlineMedium, + ), + children: [ + // Discrete slider to select the new value + if (value >= -1 && value <= max) + Slider.adaptive( + value: value == -1 ? max + 1 : value.toDouble(), + min: min.toDouble(), + max: (max + 1).toDouble(), + divisions: max - min + 1, + label: value == -1 ? '∞' : value.toString(), + onChanged: callback, + ), + if (value < -1 || value > max) + Text( + 'Manually set to $value', + style: Theme.of(context).textTheme.bodyLarge, + ), + ], + ); +} diff --git a/lib/ui/molecules/cards/animated_hidden_content_card.dart b/lib/ui/molecules/cards/animated_hidden_content_card.dart new file mode 100644 index 00000000..460118b4 --- /dev/null +++ b/lib/ui/molecules/cards/animated_hidden_content_card.dart @@ -0,0 +1,81 @@ +import 'package:flutter/material.dart'; + +class AnimatedHiddenContentCard extends StatefulWidget { + const AnimatedHiddenContentCard({ + required this.hiddenText, + required this.buttonText, + this.buttonIcon = Icons.visibility_outlined, + super.key, + }); + + final String hiddenText; + final String buttonText; + final IconData buttonIcon; + + @override + State createState() => + _AnimatedHiddenContentCardState(); +} + +class _AnimatedHiddenContentCardState extends State { + bool isKeyVisible = false; + + @override + Widget build(final BuildContext context) => Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Theme.of(context).colorScheme.surfaceContainerHighest, + ), + padding: const EdgeInsets.all(16), + child: Stack( + children: [ + SelectableText( + widget.hiddenText, + style: Theme.of(context).textTheme.titleMedium?.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + fontFamily: 'RobotoMono', + ), + ), + Positioned.fill( + child: InkWell( + onTap: () { + setState( + () { + isKeyVisible = !isKeyVisible; + }, + ); + }, + child: AnimatedOpacity( + duration: const Duration(milliseconds: 200), + opacity: isKeyVisible ? 0 : 1, + child: Container( + color: + Theme.of(context).colorScheme.surfaceContainerHighest, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + widget.buttonIcon, + size: 18.0, + ), + const SizedBox(width: 8), + Text( + widget.buttonText, + style: + Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Theme.of(context) + .colorScheme + .onSurfaceVariant, + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ); +} diff --git a/lib/ui/organisms/modals/backups/change_rotation_quotas_modal.dart b/lib/ui/organisms/modals/backups/change_rotation_quotas_modal.dart index cc4556d6..93f41575 100644 --- a/lib/ui/organisms/modals/backups/change_rotation_quotas_modal.dart +++ b/lib/ui/organisms/modals/backups/change_rotation_quotas_modal.dart @@ -4,6 +4,7 @@ import 'package:selfprivacy/logic/bloc/backups/backups_bloc.dart'; import 'package:selfprivacy/logic/bloc/server_jobs/server_jobs_bloc.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; import 'package:selfprivacy/logic/models/backup.dart'; +import 'package:selfprivacy/ui/atoms/list_tiles/quota_selection_tile.dart'; class ChangeRotationQuotasModal extends StatefulWidget { const ChangeRotationQuotasModal({ @@ -202,49 +203,3 @@ class _ChangeRotationQuotasModalState extends State { ); } } - -class QuotaSelectionTile extends StatelessWidget { - const QuotaSelectionTile({ - required this.title, - required this.subtitle, - required this.value, - required this.min, - required this.max, - required this.callback, - super.key, - }); - - final String title; - final String subtitle; - final int value; - final int min; - final int max; - final void Function(double) callback; - - @override - Widget build(final BuildContext context) => ExpansionTile( - title: Text(title), - subtitle: Text(subtitle), - trailing: Text( - value == -1 ? '∞' : value.toString(), - style: Theme.of(context).textTheme.headlineMedium, - ), - children: [ - // Discrete slider to select the new value - if (value >= -1 && value <= max) - Slider.adaptive( - value: value == -1 ? max + 1 : value.toDouble(), - min: min.toDouble(), - max: (max + 1).toDouble(), - divisions: max - min + 1, - label: value == -1 ? '∞' : value.toString(), - onChanged: callback, - ), - if (value < -1 || value > max) - Text( - 'Manually set to $value', - style: Theme.of(context).textTheme.bodyLarge, - ), - ], - ); -} diff --git a/lib/ui/organisms/modals/backups/copy_encryption_key_modal.dart b/lib/ui/organisms/modals/backups/copy_encryption_key_modal.dart index 7ea9a679..76c28629 100644 --- a/lib/ui/organisms/modals/backups/copy_encryption_key_modal.dart +++ b/lib/ui/organisms/modals/backups/copy_encryption_key_modal.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:selfprivacy/logic/bloc/backups/backups_bloc.dart'; import 'package:selfprivacy/logic/bloc/server_jobs/server_jobs_bloc.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; +import 'package:selfprivacy/ui/molecules/cards/animated_hidden_content_card.dart'; import 'package:selfprivacy/ui/molecules/info_box/info_box.dart'; import 'package:selfprivacy/utils/platform_adapter.dart'; @@ -71,62 +72,11 @@ class _CopyEncryptionKeyModalState extends State { textAlign: TextAlign.center, ), const SizedBox(height: 8), - Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: Theme.of(context).colorScheme.surfaceContainerHighest, - ), - padding: const EdgeInsets.all(16), - child: Stack( - children: [ - SelectableText( - encryptionKey, - style: Theme.of(context).textTheme.titleMedium?.copyWith( - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - Positioned.fill( - child: InkWell( - onTap: () { - setState( - () { - isKeyVisible = !isKeyVisible; - }, - ); - }, - child: AnimatedOpacity( - duration: const Duration(milliseconds: 200), - opacity: isKeyVisible ? 0 : 1, - child: Container( - color: - Theme.of(context).colorScheme.surfaceContainerHighest, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Icons.visibility_outlined), - const SizedBox(width: 8), - Text( - 'backup.backups_encryption_key_show'.tr(), - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith( - color: Theme.of(context) - .colorScheme - .onSurfaceVariant, - ), - ), - ], - ), - ), - ), - ), - ), - ], - ), + AnimatedHiddenContentCard( + buttonText: 'backup.backups_encryption_key_show'.tr(), + hiddenText: encryptionKey, ), - const SizedBox(height: 8), + const SizedBox(height: 16), FilledButton.icon( onPressed: () { setState( @@ -147,7 +97,10 @@ class _CopyEncryptionKeyModalState extends State { }); PlatformAdapter.setClipboard(encryptionKey); }, - icon: const Icon(Icons.copy_all_outlined), + icon: const Icon( + Icons.copy_all_outlined, + size: 18.0, + ), label: Text( copiedToClipboard ? 'basis.copied_to_clipboard'.tr() diff --git a/lib/ui/pages/users/users.dart b/lib/ui/pages/users/users.dart index 132c1808..616f6ed6 100644 --- a/lib/ui/pages/users/users.dart +++ b/lib/ui/pages/users/users.dart @@ -75,7 +75,10 @@ class UsersPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon(Icons.person_add_outlined), + const Icon( + Icons.person_add_outlined, + size: 18.0, + ), const SizedBox(width: 8), Text('users.new_user'.tr()), ], diff --git a/pubspec.lock b/pubspec.lock index cc53090d..70062926 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1403,10 +1403,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.2.4" + version: "14.2.5" watcher: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index d9b8e9f5..15b86878 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -91,14 +91,6 @@ flutter: - family: BrandIcons fonts: - asset: assets/fonts/BrandIcons.ttf - - family: Inter + - family: RobotoMono fonts: - - asset: assets/fonts/Inter-Regular.ttf - - asset: assets/fonts/Inter-Medium.ttf - weight: 500 - - asset: assets/fonts/Inter-SemiBold.ttf - weight: 600 - - asset: assets/fonts/Inter-Bold.ttf - weight: 700 - - asset: assets/fonts/Inter-ExtraBold.ttf - weight: 800 + - asset: assets/fonts/RobotoMono-VariableFont_wght.ttf