-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add community onboarding (wip) and privacy controls (also wip)
- Loading branch information
Showing
10 changed files
with
620 additions
and
283 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:material_symbols_icons/symbols.dart'; | ||
import 'package:pocketbase/pocketbase.dart'; | ||
import 'package:provider/provider.dart'; | ||
import 'package:reactive_forms/reactive_forms.dart'; | ||
|
||
const hideUsername = "hide_username"; | ||
|
||
class PrivacyControls extends StatefulWidget { | ||
final void Function(PrivacyControl, bool)? onChanged; | ||
|
||
const PrivacyControls({this.onChanged, super.key}); | ||
|
||
@override | ||
_PrivacyControlsState createState() => _PrivacyControlsState(); | ||
} | ||
|
||
enum PrivacyControl { hideUsernameInCommunity, hideUsernameInPrivateChallenges } | ||
|
||
class _PrivacyControlsState extends State<PrivacyControls> { | ||
final form = FormGroup({ | ||
PrivacyControl.hideUsernameInCommunity.name: | ||
FormControl<bool>(validators: [Validators.required], value: false), | ||
PrivacyControl.hideUsernameInPrivateChallenges.name: | ||
FormControl<bool>(validators: [Validators.required], value: false), | ||
}); | ||
late PocketBase pb; | ||
|
||
@override | ||
void initState() { | ||
pb = Provider.of<PocketBase>(context, listen: false); | ||
if(pb.authStore.model != null) setFormStates(pb.authStore.model); | ||
setupRealtime(); | ||
super.initState(); | ||
} | ||
|
||
void setupRealtime(){ | ||
if(pb.authStore.model != null) { | ||
pb.collection("users").subscribe(pb.authStore.model.id, (model){ | ||
if(model.record != null) setFormStates(model.record!); | ||
}); | ||
} | ||
} | ||
|
||
void setFormStates(RecordModel model){ | ||
setState(() { | ||
form.control(PrivacyControl.hideUsernameInCommunity.name).value = model.getBoolValue( | ||
PrivacyControl.hideUsernameInCommunity.name, | ||
false | ||
); | ||
form.control(PrivacyControl.hideUsernameInPrivateChallenges.name).value = model.getBoolValue( | ||
PrivacyControl.hideUsernameInPrivateChallenges.name, | ||
false | ||
); | ||
}); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return ReactiveForm( | ||
formGroup: form, | ||
child: Column( | ||
children: [ | ||
buildPrivacyControl( | ||
"Hide username in community", | ||
"Display your user ID instead of your username in the community", | ||
Symbols.disabled_visible_rounded, | ||
form.control(PrivacyControl.hideUsernameInCommunity.name).value, | ||
(value) => _updatePrivacyControl( | ||
PrivacyControl.hideUsernameInCommunity, value)), | ||
buildPrivacyControl( | ||
"Hide username in private challenges", | ||
"Display your user ID instead of your username in the invite only challenges", | ||
Symbols.shield_lock_rounded, | ||
form.control(PrivacyControl.hideUsernameInPrivateChallenges.name).value, | ||
(value) => _updatePrivacyControl( | ||
PrivacyControl.hideUsernameInPrivateChallenges, value)), | ||
], | ||
), | ||
); | ||
} | ||
|
||
void _updatePrivacyControl(PrivacyControl control, bool value) { | ||
value = !value; | ||
if (widget.onChanged != null) { | ||
widget.onChanged!(control, value); | ||
} | ||
|
||
pb.collection("users").update((pb.authStore.model as RecordModel).id, | ||
body: {control.name: value}); | ||
|
||
setState(() { | ||
form.control(control.name).value = value; | ||
}); | ||
} | ||
|
||
Widget buildPrivacyControl(String name, String description, IconData icon, | ||
bool value, void Function(bool) onPressed) { | ||
return SizedBox( | ||
width: 410, | ||
child: Card( | ||
clipBehavior: Clip.hardEdge, | ||
child: ListTile( | ||
contentPadding: | ||
const EdgeInsets.symmetric(horizontal: 20, vertical: 5), | ||
leading: Icon(icon), | ||
title: Text(name), | ||
subtitle: Text(description), | ||
onTap: () => onPressed(value), // Remove ! from !value | ||
trailing: Switch( | ||
value: value, | ||
onChanged: (value) => onPressed(!value), | ||
))), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import 'package:fitness_challenges/utils/common.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_advanced_avatar/flutter_advanced_avatar.dart'; | ||
import 'package:pocketbase/pocketbase.dart'; | ||
import 'package:provider/provider.dart'; | ||
|
||
String getUsernameFromUser(RecordModel user){ | ||
final hideUsername = user.getBoolValue("hideUsernameInCommunity", false); | ||
if(hideUsername){ | ||
return "User ${user.id}"; | ||
} else { | ||
return user.getStringValue("username", "User ${user.id}"); | ||
} | ||
} | ||
|
||
class UserPreview extends StatelessWidget { | ||
final bool forceRandomUsername; | ||
|
||
const UserPreview({super.key, this.forceRandomUsername = false}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final theme = Theme.of(context); | ||
final pb = Provider.of<PocketBase>(context, listen: false); | ||
return Card.outlined( | ||
child: Padding( | ||
padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 20), | ||
child: Column( | ||
children: [ | ||
Row( | ||
mainAxisAlignment: MainAxisAlignment.center, | ||
children: [ | ||
AdvancedAvatar( | ||
name: getUsernameFromUser(pb.authStore.model!), | ||
style: theme.textTheme.titleMedium | ||
?.copyWith(color: theme.colorScheme.onPrimary), | ||
decoration: BoxDecoration( | ||
color: theme.colorScheme.primary, | ||
borderRadius: BorderRadius.circular(50), | ||
), | ||
size: 35, | ||
), | ||
const SizedBox( | ||
width: 20, | ||
), | ||
Column( | ||
crossAxisAlignment: CrossAxisAlignment.start, | ||
children: [ | ||
Text( | ||
trimString(getUsernameFromUser(pb.authStore.model!), 15), | ||
style: theme.textTheme.headlineSmall, | ||
textAlign: TextAlign.center, | ||
), | ||
], | ||
), | ||
], | ||
), | ||
], | ||
), | ||
), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.