feat: Implement profile settings
This commit is contained in:
parent
a3a2a37a14
commit
e66bf0a10c
7 changed files with 198 additions and 20 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:fluffychat/pages/settings_profile/settings_profile_presenter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
|
@ -218,6 +219,15 @@ abstract class AppRoutes {
|
|||
: const Settings(),
|
||||
),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: 'profile_settings',
|
||||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
context,
|
||||
state,
|
||||
const SettingsProfilePresenter(),
|
||||
),
|
||||
redirect: loggedOutRedirect,
|
||||
),
|
||||
GoRoute(
|
||||
path: 'notifications',
|
||||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
|
|
|
|||
|
|
@ -2782,5 +2782,9 @@
|
|||
"description": "This should be a very short string because there is not much space in the button!"
|
||||
},
|
||||
"createNewChat": "Create new chat",
|
||||
"reset": "Reset"
|
||||
"reset": "Reset",
|
||||
"profileSettings": "Profile settings",
|
||||
"timezone": "Timezone",
|
||||
"pronouns": "Pronouns",
|
||||
"save": "Save"
|
||||
}
|
||||
|
|
@ -118,24 +118,6 @@ class SettingsView extends StatelessWidget {
|
|||
);
|
||||
},
|
||||
),
|
||||
FutureBuilder(
|
||||
future: Matrix.of(context).client.getAuthMetadata(),
|
||||
builder: (context, snapshot) {
|
||||
final accountManageUrl = snapshot.data?.issuer;
|
||||
if (accountManageUrl == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return ListTile(
|
||||
leading: const Icon(Icons.account_circle_outlined),
|
||||
title: Text(L10n.of(context).manageAccount),
|
||||
trailing: const Icon(Icons.open_in_new_outlined),
|
||||
onTap: () => launchUrl(
|
||||
accountManageUrl,
|
||||
mode: LaunchMode.inAppBrowserView,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
Divider(color: theme.dividerColor),
|
||||
SwitchListTile.adaptive(
|
||||
controlAffinity: ListTileControlAffinity.trailing,
|
||||
|
|
@ -145,6 +127,34 @@ class SettingsView extends StatelessWidget {
|
|||
onChanged: controller.firstRunBootstrapAction,
|
||||
),
|
||||
Divider(color: theme.dividerColor),
|
||||
|
||||
FutureBuilder(
|
||||
future: Matrix.of(context).client.getAuthMetadata(),
|
||||
builder: (context, snapshot) {
|
||||
final accountManageUrl = snapshot.data?.issuer;
|
||||
if (accountManageUrl == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return ListTile(
|
||||
leading: const Icon(Icons.admin_panel_settings_outlined),
|
||||
title: Text(L10n.of(context).manageAccount),
|
||||
trailing: const Icon(Icons.open_in_new_outlined),
|
||||
onTap: () => launchUrl(
|
||||
accountManageUrl,
|
||||
mode: LaunchMode.inAppBrowserView,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.account_circle_outlined),
|
||||
title: Text(L10n.of(context).profileSettings),
|
||||
tileColor:
|
||||
activeRoute.startsWith('/rooms/settings/profile_settings')
|
||||
? theme.colorScheme.surfaceContainerHigh
|
||||
: null,
|
||||
onTap: () => context.go('/rooms/settings/profile_settings'),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.format_paint_outlined),
|
||||
title: Text(L10n.of(context).changeTheme),
|
||||
|
|
|
|||
62
lib/pages/settings_profile/settings_profile_page.dart
Normal file
62
lib/pages/settings_profile/settings_profile_page.dart
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SettingsProfilePage extends StatelessWidget {
|
||||
final TextEditingController? pronounsController;
|
||||
final String? timezone;
|
||||
final VoidCallback save;
|
||||
final bool isLoading;
|
||||
|
||||
const SettingsProfilePage({
|
||||
super.key,
|
||||
required this.pronounsController,
|
||||
required this.save,
|
||||
required this.timezone,
|
||||
required this.isLoading,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: !FluffyThemes.isColumnMode(context),
|
||||
title: Text(L10n.of(context).profileSettings),
|
||||
),
|
||||
body: MaxWidthBody(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(32.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: .stretch,
|
||||
spacing: 32,
|
||||
children: [
|
||||
TextField(
|
||||
controller: pronounsController,
|
||||
readOnly: pronounsController == null,
|
||||
decoration: InputDecoration(
|
||||
labelText: L10n.of(context).pronouns,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: Material(
|
||||
elevation: 8,
|
||||
shadowColor: theme.appBarTheme.shadowColor,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: ElevatedButton(
|
||||
onPressed: pronounsController == null || isLoading ? null : save,
|
||||
child: isLoading
|
||||
? LinearProgressIndicator()
|
||||
: Text(L10n.of(context).saveChanges),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
91
lib/pages/settings_profile/settings_profile_presenter.dart
Normal file
91
lib/pages/settings_profile/settings_profile_presenter.dart
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
import 'package:fluffychat/pages/settings_profile/settings_profile_page.dart';
|
||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
class SettingsProfilePresenter extends StatefulWidget {
|
||||
const SettingsProfilePresenter({super.key});
|
||||
|
||||
@override
|
||||
State<SettingsProfilePresenter> createState() =>
|
||||
_SettingsProfilePresenterState();
|
||||
}
|
||||
|
||||
class _SettingsProfilePresenterState extends State<SettingsProfilePresenter> {
|
||||
static const String pronounsKey = 'io.fsky.nyx.pronouns';
|
||||
static const String timezoneFallbackKey = 'us.cloke.msc4175.tz';
|
||||
|
||||
TextEditingController? _pronounsController;
|
||||
String? _timezone;
|
||||
bool _isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_loadProfile();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
Future<void> _loadProfile() async {
|
||||
final client = Matrix.of(context).client;
|
||||
final cachedProfile = await client.getUserProfile(
|
||||
client.userID!,
|
||||
maxCacheAge: Duration.zero,
|
||||
);
|
||||
print(cachedProfile.additionalProperties);
|
||||
setState(() {
|
||||
_timezone =
|
||||
cachedProfile.mTz ??
|
||||
cachedProfile.additionalProperties.tryGet<String>(
|
||||
timezoneFallbackKey,
|
||||
);
|
||||
_pronounsController = TextEditingController(
|
||||
text: cachedProfile.additionalProperties.tryGet<String>(pronounsKey),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _save() async {
|
||||
final client = Matrix.of(context).client;
|
||||
final cachedProfile = await client.getUserProfile(client.userID!);
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
try {
|
||||
final newPronouns = _pronounsController!.text.trim();
|
||||
if (newPronouns !=
|
||||
cachedProfile.additionalProperties.tryGet<String>(pronounsKey)) {
|
||||
await client.setProfileField(client.userID!, pronounsKey, {
|
||||
pronounsKey: newPronouns,
|
||||
});
|
||||
}
|
||||
|
||||
if (cachedProfile.mTz != _timezone) {
|
||||
await client.setProfileField(client.userID!, 'm.tz', {
|
||||
'm.tz': _timezone,
|
||||
});
|
||||
}
|
||||
} catch (e, s) {
|
||||
Logs().e('Unable to update profile', e, s);
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context))));
|
||||
}
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => SettingsProfilePage(
|
||||
pronounsController: _pronounsController,
|
||||
save: _save,
|
||||
timezone: _timezone,
|
||||
isLoading: _isLoading,
|
||||
);
|
||||
}
|
||||
|
|
@ -1898,7 +1898,7 @@ packages:
|
|||
source: hosted
|
||||
version: "0.6.16"
|
||||
timezone:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: timezone
|
||||
sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ dependencies:
|
|||
sqflite_common_ffi: ^2.3.7+1
|
||||
sqlcipher_flutter_libs: ^0.6.8
|
||||
swipe_to_action: ^0.3.0
|
||||
timezone: ^0.10.1
|
||||
unifiedpush: ^6.2.0
|
||||
unifiedpush_ui: ^0.2.0
|
||||
universal_html: ^2.3.0
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue