mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-06 16:14:15 +00:00
refactor(ui): Use a monospace font for the encryption key
This commit is contained in:
parent
9b1abb1408
commit
8dd3d1c70b
BIN
assets/fonts/RobotoMono-VariableFont_wght.ttf
Normal file
BIN
assets/fonts/RobotoMono-VariableFont_wght.ttf
Normal file
Binary file not shown.
47
lib/ui/atoms/list_tiles/quota_selection_tile.dart
Normal file
47
lib/ui/atoms/list_tiles/quota_selection_tile.dart
Normal file
|
@ -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,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
81
lib/ui/molecules/cards/animated_hidden_content_card.dart
Normal file
81
lib/ui/molecules/cards/animated_hidden_content_card.dart
Normal file
|
@ -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<AnimatedHiddenContentCard> createState() =>
|
||||||
|
_AnimatedHiddenContentCardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AnimatedHiddenContentCardState extends State<AnimatedHiddenContentCard> {
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
|
@ -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/bloc/server_jobs/server_jobs_bloc.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/models/backup.dart';
|
import 'package:selfprivacy/logic/models/backup.dart';
|
||||||
|
import 'package:selfprivacy/ui/atoms/list_tiles/quota_selection_tile.dart';
|
||||||
|
|
||||||
class ChangeRotationQuotasModal extends StatefulWidget {
|
class ChangeRotationQuotasModal extends StatefulWidget {
|
||||||
const ChangeRotationQuotasModal({
|
const ChangeRotationQuotasModal({
|
||||||
|
@ -202,49 +203,3 @@ class _ChangeRotationQuotasModalState extends State<ChangeRotationQuotasModal> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/logic/bloc/backups/backups_bloc.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/bloc/server_jobs/server_jobs_bloc.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.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/ui/molecules/info_box/info_box.dart';
|
||||||
import 'package:selfprivacy/utils/platform_adapter.dart';
|
import 'package:selfprivacy/utils/platform_adapter.dart';
|
||||||
|
|
||||||
|
@ -71,62 +72,11 @@ class _CopyEncryptionKeyModalState extends State<CopyEncryptionKeyModal> {
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Container(
|
AnimatedHiddenContentCard(
|
||||||
decoration: BoxDecoration(
|
buttonText: 'backup.backups_encryption_key_show'.tr(),
|
||||||
borderRadius: BorderRadius.circular(20),
|
hiddenText: encryptionKey,
|
||||||
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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 16),
|
||||||
FilledButton.icon(
|
FilledButton.icon(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(
|
setState(
|
||||||
|
@ -147,7 +97,10 @@ class _CopyEncryptionKeyModalState extends State<CopyEncryptionKeyModal> {
|
||||||
});
|
});
|
||||||
PlatformAdapter.setClipboard(encryptionKey);
|
PlatformAdapter.setClipboard(encryptionKey);
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.copy_all_outlined),
|
icon: const Icon(
|
||||||
|
Icons.copy_all_outlined,
|
||||||
|
size: 18.0,
|
||||||
|
),
|
||||||
label: Text(
|
label: Text(
|
||||||
copiedToClipboard
|
copiedToClipboard
|
||||||
? 'basis.copied_to_clipboard'.tr()
|
? 'basis.copied_to_clipboard'.tr()
|
||||||
|
|
|
@ -75,7 +75,10 @@ class UsersPage extends StatelessWidget {
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.person_add_outlined),
|
const Icon(
|
||||||
|
Icons.person_add_outlined,
|
||||||
|
size: 18.0,
|
||||||
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Text('users.new_user'.tr()),
|
Text('users.new_user'.tr()),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1403,10 +1403,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vm_service
|
name: vm_service
|
||||||
sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc
|
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "14.2.4"
|
version: "14.2.5"
|
||||||
watcher:
|
watcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
12
pubspec.yaml
12
pubspec.yaml
|
@ -91,14 +91,6 @@ flutter:
|
||||||
- family: BrandIcons
|
- family: BrandIcons
|
||||||
fonts:
|
fonts:
|
||||||
- asset: assets/fonts/BrandIcons.ttf
|
- asset: assets/fonts/BrandIcons.ttf
|
||||||
- family: Inter
|
- family: RobotoMono
|
||||||
fonts:
|
fonts:
|
||||||
- asset: assets/fonts/Inter-Regular.ttf
|
- asset: assets/fonts/RobotoMono-VariableFont_wght.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
|
|
||||||
|
|
Loading…
Reference in a new issue