remove security profiles

This commit is contained in:
otsmr 2026-07-13 22:19:31 +02:00
parent f6f865a6e6
commit 3ed6c1b334
19 changed files with 35 additions and 541 deletions

View file

@ -36,8 +36,6 @@ class Routes {
'/settings/privacy/block_users'; '/settings/privacy/block_users';
static const String settingsPrivacyUserDiscovery = static const String settingsPrivacyUserDiscovery =
'/settings/privacy/user_discovery'; '/settings/privacy/user_discovery';
static const String settingsPrivacyProfileSelection =
'/settings/privacy/profile_selection';
static const String settingsNotification = '/settings/notification'; static const String settingsNotification = '/settings/notification';
static const String settingsStorage = '/settings/storage_data'; static const String settingsStorage = '/settings/storage_data';
static const String settingsStorageManage = '/settings/storage_data/manage'; static const String settingsStorageManage = '/settings/storage_data/manage';

View file

@ -590,48 +590,6 @@ abstract class AppLocalizations {
/// **'{len} contact(s)'** /// **'{len} contact(s)'**
String settingsPrivacyBlockUsersCount(Object len); String settingsPrivacyBlockUsersCount(Object len);
/// No description provided for @settingsPrivacyProfileSelectionTitle.
///
/// In en, this message translates to:
/// **'Security Profile'**
String get settingsPrivacyProfileSelectionTitle;
/// No description provided for @securityProfileTitle.
///
/// In en, this message translates to:
/// **'Security Profile'**
String get securityProfileTitle;
/// No description provided for @securityProfileSubtitle.
///
/// In en, this message translates to:
/// **'Choose the level of protection that fits your daily use. This can be changed at any time in your settings.'**
String get securityProfileSubtitle;
/// No description provided for @securityProfileNormalTitle.
///
/// In en, this message translates to:
/// **'Normal Protection'**
String get securityProfileNormalTitle;
/// No description provided for @securityProfileNormalDesc.
///
/// In en, this message translates to:
/// **'Good balance between a convenient mode without bothering you too much.'**
String get securityProfileNormalDesc;
/// No description provided for @securityProfileStrictTitle.
///
/// In en, this message translates to:
/// **'Strict Protection'**
String get securityProfileStrictTitle;
/// No description provided for @securityProfileStrictDesc.
///
/// In en, this message translates to:
/// **'Maximum anti-phishing protection but may be inconvenient.'**
String get securityProfileStrictDesc;
/// No description provided for @settingsNotification. /// No description provided for @settingsNotification.
/// ///
/// In en, this message translates to: /// In en, this message translates to:

View file

@ -268,30 +268,6 @@ class AppLocalizationsDe extends AppLocalizations {
return '$len Kontakt(e)'; return '$len Kontakt(e)';
} }
@override
String get settingsPrivacyProfileSelectionTitle => 'Sicherheitsprofil';
@override
String get securityProfileTitle => 'Sicherheitsprofil';
@override
String get securityProfileSubtitle =>
'Wähle das Schutzniveau, das zu deiner täglichen Nutzung passt. Dies kann jederzeit in den Einstellungen geändert werden.';
@override
String get securityProfileNormalTitle => 'Normaler Schutz';
@override
String get securityProfileNormalDesc =>
'Gute Balance zwischen Komfort und Sicherheit, ohne dich zu sehr einzuschränken.';
@override
String get securityProfileStrictTitle => 'Strikter Schutz';
@override
String get securityProfileStrictDesc =>
'Maximaler Schutz vor Phishing, kann aber unkomfortabel sein.';
@override @override
String get settingsNotification => 'Benachrichtigung'; String get settingsNotification => 'Benachrichtigung';

View file

@ -265,30 +265,6 @@ class AppLocalizationsEn extends AppLocalizations {
return '$len contact(s)'; return '$len contact(s)';
} }
@override
String get settingsPrivacyProfileSelectionTitle => 'Security Profile';
@override
String get securityProfileTitle => 'Security Profile';
@override
String get securityProfileSubtitle =>
'Choose the level of protection that fits your daily use. This can be changed at any time in your settings.';
@override
String get securityProfileNormalTitle => 'Normal Protection';
@override
String get securityProfileNormalDesc =>
'Good balance between a convenient mode without bothering you too much.';
@override
String get securityProfileStrictTitle => 'Strict Protection';
@override
String get securityProfileStrictDesc =>
'Maximum anti-phishing protection but may be inconvenient.';
@override @override
String get settingsNotification => 'Notification'; String get settingsNotification => 'Notification';

@ -1 +1 @@
Subproject commit 5f16b9cdd5ddba6086741bfb945564e3d16cee85 Subproject commit b7d703c82a5ac0b6776847cb4eb6d637620f6585

View file

@ -40,9 +40,6 @@ class UserData {
@JsonKey(defaultValue: SetupProfile.standard) @JsonKey(defaultValue: SetupProfile.standard)
SetupProfile setupProfile = SetupProfile.standard; SetupProfile setupProfile = SetupProfile.standard;
@JsonKey(defaultValue: SecurityProfile.normal)
SecurityProfile securityProfile = SecurityProfile.normal;
// --- SUBSCRIPTION DTA --- // --- SUBSCRIPTION DTA ---
@JsonKey(defaultValue: 'Free') @JsonKey(defaultValue: 'Free')

View file

@ -23,12 +23,6 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) =>
..setupProfile = ..setupProfile =
$enumDecodeNullable(_$SetupProfileEnumMap, json['setupProfile']) ?? $enumDecodeNullable(_$SetupProfileEnumMap, json['setupProfile']) ??
SetupProfile.standard SetupProfile.standard
..securityProfile =
$enumDecodeNullable(
_$SecurityProfileEnumMap,
json['securityProfile'],
) ??
SecurityProfile.normal
..subscriptionPlanIdStore = json['subscriptionPlanIdStore'] as String? ..subscriptionPlanIdStore = json['subscriptionPlanIdStore'] as String?
..lastImageSend = json['lastImageSend'] == null ..lastImageSend = json['lastImageSend'] == null
? null ? null
@ -132,7 +126,6 @@ Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{
'isDeveloper': instance.isDeveloper, 'isDeveloper': instance.isDeveloper,
'deviceId': instance.deviceId, 'deviceId': instance.deviceId,
'setupProfile': _$SetupProfileEnumMap[instance.setupProfile]!, 'setupProfile': _$SetupProfileEnumMap[instance.setupProfile]!,
'securityProfile': _$SecurityProfileEnumMap[instance.securityProfile]!,
'subscriptionPlan': instance.subscriptionPlan, 'subscriptionPlan': instance.subscriptionPlan,
'subscriptionPlanIdStore': instance.subscriptionPlanIdStore, 'subscriptionPlanIdStore': instance.subscriptionPlanIdStore,
'lastImageSend': instance.lastImageSend?.toIso8601String(), 'lastImageSend': instance.lastImageSend?.toIso8601String(),
@ -192,12 +185,6 @@ Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{
const _$SetupProfileEnumMap = { const _$SetupProfileEnumMap = {
SetupProfile.standard: 'standard', SetupProfile.standard: 'standard',
SetupProfile.customized: 'customized', SetupProfile.customized: 'customized',
SetupProfile.maximum: 'maximum',
};
const _$SecurityProfileEnumMap = {
SecurityProfile.normal: 'normal',
SecurityProfile.strict: 'strict',
}; };
const _$ThemeModeEnumMap = { const _$ThemeModeEnumMap = {

View file

@ -40,7 +40,6 @@ import 'package:twonly/src/visual/views/settings/help/help.view.dart';
import 'package:twonly/src/visual/views/settings/notification.view.dart'; import 'package:twonly/src/visual/views/settings/notification.view.dart';
import 'package:twonly/src/visual/views/settings/privacy.view.dart'; import 'package:twonly/src/visual/views/settings/privacy.view.dart';
import 'package:twonly/src/visual/views/settings/privacy/block_users.view.dart'; import 'package:twonly/src/visual/views/settings/privacy/block_users.view.dart';
import 'package:twonly/src/visual/views/settings/privacy/profile_selection.view.dart';
import 'package:twonly/src/visual/views/settings/privacy/user_discovery.view.dart'; import 'package:twonly/src/visual/views/settings/privacy/user_discovery.view.dart';
import 'package:twonly/src/visual/views/settings/profile/modify_avatar.view.dart'; import 'package:twonly/src/visual/views/settings/profile/modify_avatar.view.dart';
import 'package:twonly/src/visual/views/settings/profile/profile.view.dart'; import 'package:twonly/src/visual/views/settings/profile/profile.view.dart';
@ -220,10 +219,6 @@ final routerProvider = GoRouter(
path: 'user_discovery', path: 'user_discovery',
builder: (context, state) => const UserDiscoverySettingsView(), builder: (context, state) => const UserDiscoverySettingsView(),
), ),
GoRoute(
path: 'profile_selection',
builder: (context, state) => const ProfileSelectionSettingsView(),
),
], ],
), ),
GoRoute( GoRoute(

View file

@ -1,8 +1 @@
enum SetupProfile { standard, customized, maximum } enum SetupProfile { standard, customized }
enum SecurityProfile { normal, strict }
extension SecurityProfileExtension on SecurityProfile {
bool get showWarningForNonVerifiedContacts => this == SecurityProfile.strict;
bool get showOnlyVerifiedInChatViewList => this == SecurityProfile.normal;
}

View file

@ -2,11 +2,9 @@ import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart' import 'package:font_awesome_flutter/font_awesome_flutter.dart'
show FaIcon, FontAwesomeIcons; show FaIcon, FontAwesomeIcons;
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:twonly/locator.dart';
import 'package:twonly/src/constants/routes.keys.dart'; import 'package:twonly/src/constants/routes.keys.dart';
import 'package:twonly/src/database/daos/contacts.dao.dart'; import 'package:twonly/src/database/daos/contacts.dao.dart';
import 'package:twonly/src/database/twonly.db.dart'; import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/services/profile.service.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/visual/components/profile_qr_code.comp.dart'; import 'package:twonly/src/visual/components/profile_qr_code.comp.dart';
import 'package:twonly/src/visual/elements/my_button.element.dart'; import 'package:twonly/src/visual/elements/my_button.element.dart';
@ -122,18 +120,16 @@ class VerificationBadgeInfo extends StatelessWidget {
], ],
), ),
), ),
if (userService.currentUser.securityProfile != SecurityProfile.strict || _buildItem(
userService.currentUser.isUserDiscoveryEnabled) context,
_buildItem( icon: const SvgIcon(
context, assetPath: SvgIcons.verifiedGreen,
icon: const SvgIcon( size: 40,
assetPath: SvgIcons.verifiedGreen, color: colorVerificationBadgeYellow,
size: 40,
color: colorVerificationBadgeYellow,
),
description: context.lang.verificationBadgeYellowDesc,
boldTextColor: colorVerificationBadgeYellow,
), ),
description: context.lang.verificationBadgeYellowDesc,
boldTextColor: colorVerificationBadgeYellow,
),
_buildItem( _buildItem(
context, context,
icon: const SvgIcon(assetPath: SvgIcons.verifiedRed, size: 40), icon: const SvgIcon(assetPath: SvgIcons.verifiedRed, size: 40),

View file

@ -11,7 +11,6 @@ import 'package:twonly/src/database/tables/mediafiles.table.dart';
import 'package:twonly/src/database/tables/messages.table.dart'; import 'package:twonly/src/database/tables/messages.table.dart';
import 'package:twonly/src/database/twonly.db.dart'; import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/services/api/mediafiles/download.api.dart'; import 'package:twonly/src/services/api/mediafiles/download.api.dart';
import 'package:twonly/src/services/profile.service.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/visual/components/avatar_icon.comp.dart'; import 'package:twonly/src/visual/components/avatar_icon.comp.dart';
import 'package:twonly/src/visual/components/flame_counter.comp.dart'; import 'package:twonly/src/visual/components/flame_counter.comp.dart';
@ -242,10 +241,7 @@ class _UserListItem extends State<GroupListItemComp> {
const SizedBox(width: 3), const SizedBox(width: 3),
VerificationBadgeComp( VerificationBadgeComp(
group: widget.group, group: widget.group,
showOnlyIfVerified: userService showOnlyIfVerified: true,
.currentUser
.securityProfile
.showOnlyVerifiedInChatViewList,
clickable: false, clickable: false,
size: 12, size: 12,
), ),

View file

@ -21,7 +21,6 @@ import 'package:twonly/src/visual/views/chats/chat_messages_components/bottom_sh
import 'package:twonly/src/visual/views/chats/chat_messages_components/entries/chat_audio_entry.dart'; import 'package:twonly/src/visual/views/chats/chat_messages_components/entries/chat_audio_entry.dart';
import 'package:twonly/src/visual/views/chats/chat_messages_components/message_input_components/ask_for_friend_promotions.comp.dart'; import 'package:twonly/src/visual/views/chats/chat_messages_components/message_input_components/ask_for_friend_promotions.comp.dart';
import 'package:twonly/src/visual/views/chats/chat_messages_components/message_input_components/sparks.comp.dart'; import 'package:twonly/src/visual/views/chats/chat_messages_components/message_input_components/sparks.comp.dart';
import 'package:twonly/src/visual/views/chats/chat_messages_components/message_input_components/unverified_contact_warning.comp.dart';
import 'package:twonly/src/visual/views/chats/chat_messages_components/message_input_components/user_discovery_manual_approval.comp.dart'; import 'package:twonly/src/visual/views/chats/chat_messages_components/message_input_components/user_discovery_manual_approval.comp.dart';
import 'package:twonly/src/visual/views/contact/contact_components/restore_flame.comp.dart'; import 'package:twonly/src/visual/views/contact/contact_components/restore_flame.comp.dart';
@ -283,11 +282,9 @@ class _MessageInputState extends State<MessageInput> {
flameOnRightSide: true, flameOnRightSide: true,
), ),
), ),
UnverifiedContactWarningComp( Padding(
group: widget.group, padding: const EdgeInsets.only(left: 10, bottom: 10),
child: Padding( child: Row(
padding: const EdgeInsets.only(left: 10, bottom: 10),
child: Row(
children: [ children: [
Expanded( Expanded(
child: Container( child: Container(
@ -589,7 +586,6 @@ class _MessageInputState extends State<MessageInput> {
], ],
), ),
), ),
),
Offstage( Offstage(
offstage: !_emojiShowing, offstage: !_emojiShowing,
child: EmojiPicker( child: EmojiPicker(

View file

@ -1,142 +0,0 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:twonly/locator.dart';
import 'package:twonly/src/constants/routes.keys.dart';
import 'package:twonly/src/database/daos/key_verification.dao.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/services/profile.service.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/visual/components/verification_badge.comp.dart';
class UnverifiedContactWarningComp extends StatelessWidget {
const UnverifiedContactWarningComp({
required this.group,
required this.child,
super.key,
});
final Group group;
final Widget child;
@override
Widget build(BuildContext context) {
return StreamBuilder<void>(
stream: userService.onUserUpdated,
builder: (context, _) {
if (!userService
.currentUser
.securityProfile
.showWarningForNonVerifiedContacts) {
return child;
}
return StreamBuilder<VerificationStatus>(
stream: twonlyDB.keyVerificationDao.watchAllGroupMembersVerified(
group.groupId,
),
builder: (context, snapshot) {
final status = snapshot.data;
if (status == null || status == VerificationStatus.trusted) {
return child;
}
return Container(
margin: const EdgeInsets.only(top: 8),
decoration: BoxDecoration(
color: context.color.errorContainer.withValues(alpha: 0.5),
borderRadius: BorderRadius.circular(24),
border: Border.all(
color: context.color.error.withValues(alpha: 0.5),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(12, 10, 12, 8),
child: Row(
children: [
VerificationBadgeComp(
group: group,
size: 24,
clickable: false,
),
const SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
group.isDirectChat
? context.lang.unverifiedWarningDirectTitle
: context.lang.unverifiedWarningGroupTitle,
style: TextStyle(
color: context.color.onErrorContainer,
fontWeight: FontWeight.bold,
fontSize: 13,
height: 1.2,
),
),
const SizedBox(height: 4),
RichText(
text: TextSpan(
style: TextStyle(
color: context.color.onErrorContainer,
fontSize: 11,
),
children: formattedText(
context,
context.lang.unverifiedWarningBody,
textColor: context.color.onErrorContainer,
),
),
),
],
),
),
const SizedBox(width: 10),
SizedBox(
height: 30,
child: FilledButton.tonal(
style: FilledButton.styleFrom(
backgroundColor: context.color.onErrorContainer,
foregroundColor: context.color.errorContainer,
padding: const EdgeInsets.symmetric(
horizontal: 10,
),
textStyle: const TextStyle(
fontSize: 11,
fontWeight: FontWeight.bold,
),
),
onPressed: () async {
if (group.isDirectChat) {
await context.push(
Routes.settingsHelpFaqVerifyBadge,
);
} else {
await context.push(
Routes.profileGroup(group.groupId),
);
}
},
child: Text(context.lang.unverifiedWarningButton),
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(
top: 5,
),
child: child,
),
],
),
);
},
);
},
);
}
}

View file

@ -10,7 +10,6 @@ import 'package:twonly/src/visual/views/onboarding/setup/backup.setup.dart';
import 'package:twonly/src/visual/views/onboarding/setup/let_your_friends_find_you.setup.dart'; import 'package:twonly/src/visual/views/onboarding/setup/let_your_friends_find_you.setup.dart';
import 'package:twonly/src/visual/views/onboarding/setup/profile.setup.dart'; import 'package:twonly/src/visual/views/onboarding/setup/profile.setup.dart';
import 'package:twonly/src/visual/views/onboarding/setup/profile_selection.setup.dart'; import 'package:twonly/src/visual/views/onboarding/setup/profile_selection.setup.dart';
import 'package:twonly/src/visual/views/onboarding/setup/security_profile.setup.dart';
import 'package:twonly/src/visual/views/onboarding/setup/share_your_friends.setup.dart'; import 'package:twonly/src/visual/views/onboarding/setup/share_your_friends.setup.dart';
import 'package:twonly/src/visual/views/settings/privacy/user_discovery/components/user_discovery_setup.comp.dart'; import 'package:twonly/src/visual/views/settings/privacy/user_discovery/components/user_discovery_setup.comp.dart';
@ -18,7 +17,6 @@ enum SetupPages {
profile, profile,
backup, backup,
profileSelection, profileSelection,
securityProfile,
shareYourFriends, shareYourFriends,
letYourFriendsFindYou, letYourFriendsFindYou,
} }
@ -40,18 +38,11 @@ extension SetupPagesExtension on SetupPages {
SetupPages.backup, SetupPages.backup,
SetupPages.profileSelection, SetupPages.profileSelection,
]; ];
case SetupProfile.maximum:
return [
SetupPages.profile,
SetupPages.backup,
SetupPages.profileSelection,
];
case SetupProfile.customized: case SetupProfile.customized:
return [ return [
SetupPages.profile, SetupPages.profile,
SetupPages.backup, SetupPages.backup,
SetupPages.profileSelection, SetupPages.profileSelection,
SetupPages.securityProfile,
SetupPages.shareYourFriends, SetupPages.shareYourFriends,
SetupPages.letYourFriendsFindYou, SetupPages.letYourFriendsFindYou,
]; ];
@ -218,8 +209,6 @@ class _SetupViewState extends State<SetupView> {
return const BackupSetupPage(); return const BackupSetupPage();
case SetupPages.profileSelection: case SetupPages.profileSelection:
return const ProfileSelectionSetup(); return const ProfileSelectionSetup();
case SetupPages.securityProfile:
return const SecurityProfileSetup();
case SetupPages.shareYourFriends: case SetupPages.shareYourFriends:
return ShareYourFriendsSetupPage(state: state); return ShareYourFriendsSetupPage(state: state);
case SetupPages.letYourFriendsFindYou: case SetupPages.letYourFriendsFindYou:

View file

@ -12,7 +12,7 @@ class SafetyProfileCard extends StatelessWidget {
super.key, super.key,
}); });
final Object profile; final SetupProfile profile;
final bool isSelected; final bool isSelected;
final VoidCallback onTap; final VoidCallback onTap;
final bool isHovered; final bool isHovered;
@ -32,60 +32,24 @@ class SafetyProfileCard extends StatelessWidget {
final IconData icon; final IconData icon;
final String? badgeText; final String? badgeText;
if (profile is SetupProfile) { switch (profile) {
switch (profile as SetupProfile) { case SetupProfile.standard:
case SetupProfile.standard: title = context.lang.onboardingProfileSelectionDefaultTitle;
title = context.lang.onboardingProfileSelectionDefaultTitle; subtitle = Text(
subtitle = Text( context.lang.onboardingProfileSelectionDefaultDesc,
context.lang.onboardingProfileSelectionDefaultDesc, style: bodyMediumStyle,
style: bodyMediumStyle, );
); icon = Icons.bolt_rounded;
icon = Icons.bolt_rounded; badgeText = context.lang.onboardingProfileSelectionDefaultBadge;
badgeText = context.lang.onboardingProfileSelectionDefaultBadge; case SetupProfile.customized:
case SetupProfile.customized: title = context.lang.onboardingProfileSelectionCustomizeTitle;
title = context.lang.onboardingProfileSelectionCustomizeTitle; subtitle = Text(
subtitle = Text( context.lang.onboardingProfileSelectionCustomizeDesc,
context.lang.onboardingProfileSelectionCustomizeDesc, style: bodyMediumStyle,
style: bodyMediumStyle, );
); icon = Icons.tune_rounded;
icon = Icons.tune_rounded; badgeText = null;
badgeText = null;
case SetupProfile.maximum:
title = context.lang.onboardingProfileSelectionStrictTitle;
subtitle = RichText(
text: TextSpan(
style: bodyMediumStyle,
children: formattedText(
context,
context.lang.onboardingProfileSelectionStrictDesc,
boldTextColor: context.color.onSurface,
),
),
);
icon = Icons.lock_outline_rounded;
badgeText = null;
}
} else if (profile is SecurityProfile) {
switch (profile as SecurityProfile) {
case SecurityProfile.normal:
title = context.lang.securityProfileNormalTitle;
subtitle = Text(
context.lang.securityProfileNormalDesc,
style: bodyMediumStyle,
);
icon = Icons.shield_outlined;
badgeText = null;
case SecurityProfile.strict:
title = context.lang.securityProfileStrictTitle;
subtitle = Text(
context.lang.securityProfileStrictDesc,
style: bodyMediumStyle,
);
icon = Icons.verified_user_outlined;
badgeText = null;
}
} else {
throw ArgumentError('Invalid profile type: $profile');
} }
return MouseRegion( return MouseRegion(

View file

@ -21,11 +21,6 @@ class _ProfileSelectionSetupState extends State<ProfileSelectionSetup> {
Future<void> _onProfileTapped(SetupProfile profile) async { Future<void> _onProfileTapped(SetupProfile profile) async {
await UserService.update((user) { await UserService.update((user) {
user.setupProfile = profile; user.setupProfile = profile;
if (profile == SetupProfile.standard) {
user.securityProfile = SecurityProfile.normal;
} else if (profile == SetupProfile.maximum) {
user.securityProfile = SecurityProfile.strict;
}
}); });
} }
@ -76,16 +71,7 @@ class _ProfileSelectionSetupState extends State<ProfileSelectionSetup> {
}), }),
onTap: () => _onProfileTapped(SetupProfile.customized), onTap: () => _onProfileTapped(SetupProfile.customized),
), ),
const SizedBox(height: 16),
SafetyProfileCard(
profile: SetupProfile.maximum,
isSelected: selectedProfile == SetupProfile.maximum,
isHovered: _hoveredProfile == SetupProfile.maximum,
onHover: (hovered) => setState(() {
_hoveredProfile = hovered ? SetupProfile.maximum : null;
}),
onTap: () => _onProfileTapped(SetupProfile.maximum),
),
const SizedBox(height: 40), const SizedBox(height: 40),
NextButtonComp( NextButtonComp(
key: ValueKey(selectedProfile), key: ValueKey(selectedProfile),

View file

@ -1,79 +0,0 @@
import 'package:flutter/material.dart';
import 'package:twonly/locator.dart';
import 'package:twonly/src/services/profile.service.dart';
import 'package:twonly/src/services/user.service.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/visual/views/onboarding/setup/components/next_button.comp.dart';
import 'package:twonly/src/visual/views/onboarding/setup/components/profile_card.comp.dart';
class SecurityProfileSetup extends StatefulWidget {
const SecurityProfileSetup({super.key});
@override
State<SecurityProfileSetup> createState() => _SecurityProfileSetupState();
}
class _SecurityProfileSetupState extends State<SecurityProfileSetup> {
SecurityProfile? _hoveredProfile;
Future<void> _onProfileTapped(SecurityProfile profile) async {
await UserService.update((user) {
user.securityProfile = profile;
});
}
@override
Widget build(BuildContext context) {
return StreamBuilder<void>(
stream: userService.onUserUpdated,
builder: (context, snapshot) {
final user = userService.currentUser;
final selectedProfile = user.securityProfile;
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
context.lang.securityProfileTitle,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Text(
context.lang.securityProfileSubtitle,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: context.color.onSurfaceVariant,
),
),
const SizedBox(height: 32),
SafetyProfileCard(
profile: SecurityProfile.normal,
isSelected: selectedProfile == SecurityProfile.normal,
isHovered: _hoveredProfile == SecurityProfile.normal,
onHover: (hovered) => setState(() {
_hoveredProfile = hovered ? SecurityProfile.normal : null;
}),
onTap: () => _onProfileTapped(SecurityProfile.normal),
),
const SizedBox(height: 16),
SafetyProfileCard(
profile: SecurityProfile.strict,
isSelected: selectedProfile == SecurityProfile.strict,
isHovered: _hoveredProfile == SecurityProfile.strict,
onHover: (hovered) => setState(() {
_hoveredProfile = hovered ? SecurityProfile.strict : null;
}),
onTap: () => _onProfileTapped(SecurityProfile.strict),
),
const SizedBox(height: 40),
const NextButtonComp(),
],
);
},
);
}
}

View file

@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:twonly/locator.dart'; import 'package:twonly/locator.dart';
import 'package:twonly/src/constants/routes.keys.dart'; import 'package:twonly/src/constants/routes.keys.dart';
import 'package:twonly/src/services/profile.service.dart';
import 'package:twonly/src/services/user.service.dart'; import 'package:twonly/src/services/user.service.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/visual/components/verification_badge_info.comp.dart'; import 'package:twonly/src/visual/components/verification_badge_info.comp.dart';
@ -83,18 +82,6 @@ class _PrivacyViewState extends State<PrivacyView> {
setState(() {}); setState(() {});
}, },
), ),
ListTile(
title: Text(context.lang.settingsPrivacyProfileSelectionTitle),
subtitle: Text(
userService.currentUser.securityProfile == SecurityProfile.strict
? context.lang.securityProfileStrictTitle
: context.lang.securityProfileNormalTitle,
),
onTap: () async {
await context.push(Routes.settingsPrivacyProfileSelection);
setState(() {});
},
),
const Divider(), const Divider(),
ListTile( ListTile(
title: Text(context.lang.settingsTypingIndication), title: Text(context.lang.settingsTypingIndication),

View file

@ -1,79 +0,0 @@
import 'package:flutter/material.dart';
import 'package:twonly/locator.dart';
import 'package:twonly/src/services/profile.service.dart';
import 'package:twonly/src/services/user.service.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/visual/views/onboarding/setup/components/profile_card.comp.dart';
class ProfileSelectionSettingsView extends StatefulWidget {
const ProfileSelectionSettingsView({super.key});
@override
State<ProfileSelectionSettingsView> createState() =>
_ProfileSelectionSettingsViewState();
}
class _ProfileSelectionSettingsViewState
extends State<ProfileSelectionSettingsView> {
SecurityProfile? _hoveredProfile;
Future<void> _onProfileTapped(SecurityProfile profile) async {
await UserService.update((user) {
user.securityProfile = profile;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(context.lang.securityProfileTitle),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(24),
child: StreamBuilder<void>(
stream: userService.onUserUpdated,
builder: (context, snapshot) {
final user = userService.currentUser;
final selectedProfile = user.securityProfile;
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
context.lang.securityProfileSubtitle,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: context.color.onSurfaceVariant,
),
),
const SizedBox(height: 32),
SafetyProfileCard(
profile: SecurityProfile.normal,
isSelected: selectedProfile == SecurityProfile.normal,
isHovered: _hoveredProfile == SecurityProfile.normal,
onHover: (hovered) => setState(() {
_hoveredProfile = hovered ? SecurityProfile.normal : null;
}),
onTap: () => _onProfileTapped(SecurityProfile.normal),
),
const SizedBox(height: 16),
SafetyProfileCard(
profile: SecurityProfile.strict,
isSelected: selectedProfile == SecurityProfile.strict,
isHovered: _hoveredProfile == SecurityProfile.strict,
onHover: (hovered) => setState(() {
_hoveredProfile = hovered ? SecurityProfile.strict : null;
}),
onTap: () => _onProfileTapped(SecurityProfile.strict),
),
],
);
},
),
),
),
);
}
}