Skip to content

Commit

Permalink
Add account settings to main settings (thunder-app#966)
Browse files Browse the repository at this point in the history
micahmo authored Dec 8, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent ca8f170 commit f19c355
Showing 10 changed files with 271 additions and 229 deletions.
58 changes: 17 additions & 41 deletions lib/account/pages/account_page.dart
Original file line number Diff line number Diff line change
@@ -3,11 +3,9 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import 'package:thunder/account/bloc/account_bloc.dart';
import 'package:thunder/account/utils/profiles.dart';
import 'package:thunder/account/widgets/account_placeholder.dart';
import 'package:thunder/core/auth/bloc/auth_bloc.dart';
import 'package:thunder/thunder/bloc/thunder_bloc.dart';
import 'package:thunder/user/pages/user_page.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class AccountPage extends StatefulWidget {
const AccountPage({super.key});
@@ -19,47 +17,25 @@ class AccountPage extends StatefulWidget {
class _AccountPageState extends State<AccountPage> {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);

AuthState authState = context.read<AuthBloc>().state;
AccountState accountState = context.read<AccountBloc>().state;
String anonymousInstance = context.watch<ThunderBloc>().state.currentAnonymousInstance;

return MultiBlocListener(
listeners: [
BlocListener<AuthBloc, AuthState>(
listener: (context, state) {
setState(() => authState = state);
},
),
BlocListener<AccountBloc, AccountState>(
listener: (context, state) {
setState(() => accountState = state);
},
),
],
child: (authState.isLoggedIn && accountState.status == AccountStatus.success && accountState.personView != null)
? UserPage(userId: accountState.personView!.person.id, isAccountUser: true)
: Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.people_rounded, size: 100, color: theme.dividerColor),
const SizedBox(height: 16),
Text(AppLocalizations.of(context)!.browsingAnonymously(anonymousInstance), textAlign: TextAlign.center),
Text(AppLocalizations.of(context)!.addAccountToSeeProfile, textAlign: TextAlign.center),
const SizedBox(height: 24.0),
ElevatedButton(
style: ElevatedButton.styleFrom(minimumSize: const Size.fromHeight(60)),
child: Text(AppLocalizations.of(context)!.manageAccounts),
onPressed: () => showProfileModalSheet(context),
)
],
),
),
));
listeners: [
BlocListener<AuthBloc, AuthState>(
listener: (context, state) {
setState(() => authState = state);
},
),
BlocListener<AccountBloc, AccountState>(
listener: (context, state) {
setState(() => accountState = state);
},
),
],
child: (authState.isLoggedIn && accountState.status == AccountStatus.success && accountState.personView != null)
? UserPage(userId: accountState.personView!.person.id, isAccountUser: true)
: const AccountPlaceholder(),
);
}
}
37 changes: 37 additions & 0 deletions lib/account/widgets/account_placeholder.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:thunder/account/utils/profiles.dart';
import 'package:thunder/thunder/bloc/thunder_bloc.dart';

class AccountPlaceholder extends StatelessWidget {
const AccountPlaceholder({super.key});

@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
String anonymousInstance = context.watch<ThunderBloc>().state.currentAnonymousInstance;

return Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.people_rounded, size: 100, color: theme.dividerColor),
const SizedBox(height: 16),
Text(AppLocalizations.of(context)!.browsingAnonymously(anonymousInstance), textAlign: TextAlign.center),
Text(AppLocalizations.of(context)!.addAccountToSeeProfile, textAlign: TextAlign.center),
const SizedBox(height: 24.0),
ElevatedButton(
style: ElevatedButton.styleFrom(minimumSize: const Size.fromHeight(60)),
child: Text(AppLocalizations.of(context)!.manageAccounts),
onPressed: () => showProfileModalSheet(context),
)
],
),
),
);
}
}
2 changes: 1 addition & 1 deletion lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@
"@add": {},
"addAccount": "Add Account",
"@addAccount": {},
"addAccountToSeeProfile": "Add an account to see your profile.",
"addAccountToSeeProfile": "Log in to see your account.",
"@addAccountToSeeProfile": {},
"addAnonymousInstance": "Add Anonymous Instance",
"@addAnonymousInstance": {},
12 changes: 11 additions & 1 deletion lib/routes.dart
Original file line number Diff line number Diff line change
@@ -16,8 +16,8 @@ import 'package:thunder/settings/pages/gesture_settings_page.dart';
import 'package:thunder/settings/pages/post_appearance_settings_page.dart';
import 'package:thunder/settings/pages/theme_settings_page.dart';
import 'package:thunder/settings/settings.dart';
import 'package:thunder/thunder/bloc/thunder_bloc.dart';
import 'package:thunder/thunder/thunder.dart';
import 'package:thunder/user/pages/user_settings_page.dart';

final GoRouter router = GoRouter(
debugLogDiagnostics: true,
@@ -115,6 +115,16 @@ final GoRouter router = GoRouter(
);
},
),
GoRoute(
name: 'account',
path: 'account',
builder: (context, state) {
return BlocProvider.value(
value: state.extra! as ThunderBloc,
child: const UserSettingsPage(),
);
},
),
GoRoute(
name: 'about',
path: 'about',
1 change: 1 addition & 0 deletions lib/settings/pages/settings_page.dart
Original file line number Diff line number Diff line change
@@ -30,6 +30,7 @@ class SettingsPage extends StatelessWidget {
SettingTopic(title: l10n.gestures, icon: Icons.swipe, path: '/settings/gestures'),
SettingTopic(title: l10n.floatingActionButton, icon: Icons.settings_applications_rounded, path: '/settings/fab'),
SettingTopic(title: l10n.accessibility, icon: Icons.accessibility, path: '/settings/accessibility'),
SettingTopic(title: l10n.account, icon: Icons.person_rounded, path: '/settings/account'),
SettingTopic(title: l10n.about, icon: Icons.info_rounded, path: '/settings/about'),
SettingTopic(title: l10n.debug, icon: Icons.developer_mode_rounded, path: '/settings/debug'),
];
56 changes: 30 additions & 26 deletions lib/user/bloc/user_settings_bloc.dart
Original file line number Diff line number Diff line change
@@ -24,6 +24,10 @@ EventTransformer<E> throttleDroppable<E>(Duration duration) {

class UserSettingsBloc extends Bloc<UserSettingsEvent, UserSettingsState> {
UserSettingsBloc() : super(const UserSettingsState()) {
on<ResetUserSettingsEvent>(
_resetUserSettingsEvent,
transformer: throttleDroppable(throttleDuration),
);
on<GetUserSettingsEvent>(
_getUserSettingsEvent,
transformer: throttleDroppable(throttleDuration),
@@ -50,17 +54,18 @@ class UserSettingsBloc extends Bloc<UserSettingsEvent, UserSettingsState> {
);
}

Future<void> _resetUserSettingsEvent(ResetUserSettingsEvent event, emit) async {
return emit(state.copyWith(status: UserSettingsStatus.initial));
}

Future<void> _getUserSettingsEvent(GetUserSettingsEvent event, emit) async {
LemmyApiV3 lemmy = LemmyClient.instance.lemmyApiV3;
Account? account = await fetchActiveProfileAccount();

final l10n = AppLocalizations.of(GlobalContext.context)!;

if (account == null) {
return emit(state.copyWith(
status: UserSettingsStatus.failure,
errorMessage: l10n.userNotLoggedIn,
));
return emit(state.copyWith(status: UserSettingsStatus.notLoggedIn));
}

try {
@@ -86,10 +91,7 @@ class UserSettingsBloc extends Bloc<UserSettingsEvent, UserSettingsState> {
final l10n = AppLocalizations.of(GlobalContext.context)!;

if (account == null) {
return emit(state.copyWith(
status: UserSettingsStatus.failure,
errorMessage: l10n.userNotLoggedIn,
));
return emit(state.copyWith(status: UserSettingsStatus.notLoggedIn));
}

GetSiteResponse originalGetSiteResponse = state.getSiteResponse!;
@@ -137,25 +139,27 @@ class UserSettingsBloc extends Bloc<UserSettingsEvent, UserSettingsState> {
LemmyApiV3 lemmy = LemmyClient.instance.lemmyApiV3;
Account? account = await fetchActiveProfileAccount();

if (account == null) {
return emit(state.copyWith(status: UserSettingsStatus.notLoggedIn));
}

try {
if (account != null) {
GetSiteResponse getSiteResponse = await lemmy.run(
GetSite(auth: account.jwt),
);

final personBlocks = getSiteResponse.myUser!.personBlocks.map((personBlockView) => personBlockView.target).toList()..sort((a, b) => a.name.compareTo(b.name));
final communityBlocks = getSiteResponse.myUser!.communityBlocks.map((communityBlockView) => communityBlockView.community).toList()..sort((a, b) => a.name.compareTo(b.name));
final instanceBlocks = getSiteResponse.myUser!.instanceBlocks?.map((instanceBlockView) => instanceBlockView.instance).toList()?..sort((a, b) => a.domain.compareTo(b.domain));

return emit(state.copyWith(
status: (state.instanceBeingBlocked != 0 && (instanceBlocks?.any((Instance instance) => instance.id == state.instanceBeingBlocked) ?? false))
? UserSettingsStatus.revert
: UserSettingsStatus.success,
personBlocks: personBlocks,
communityBlocks: communityBlocks,
instanceBlocks: instanceBlocks,
));
}
GetSiteResponse getSiteResponse = await lemmy.run(
GetSite(auth: account.jwt),
);

final personBlocks = getSiteResponse.myUser!.personBlocks.map((personBlockView) => personBlockView.target).toList()..sort((a, b) => a.name.compareTo(b.name));
final communityBlocks = getSiteResponse.myUser!.communityBlocks.map((communityBlockView) => communityBlockView.community).toList()..sort((a, b) => a.name.compareTo(b.name));
final instanceBlocks = getSiteResponse.myUser!.instanceBlocks?.map((instanceBlockView) => instanceBlockView.instance).toList()?..sort((a, b) => a.domain.compareTo(b.domain));

return emit(state.copyWith(
status: (state.instanceBeingBlocked != 0 && (instanceBlocks?.any((Instance instance) => instance.id == state.instanceBeingBlocked) ?? false))
? UserSettingsStatus.revert
: UserSettingsStatus.success,
personBlocks: personBlocks,
communityBlocks: communityBlocks,
instanceBlocks: instanceBlocks,
));
} catch (e) {
return emit(state.copyWith(status: UserSettingsStatus.failure, errorMessage: e is LemmyApiException ? getErrorMessage(GlobalContext.context, e.message) : e.toString()));
}
8 changes: 5 additions & 3 deletions lib/user/bloc/user_settings_event.dart
Original file line number Diff line number Diff line change
@@ -7,6 +7,10 @@ abstract class UserSettingsEvent extends Equatable {
List<Object> get props => [];
}

class ResetUserSettingsEvent extends UserSettingsEvent {
const ResetUserSettingsEvent();
}

class GetUserSettingsEvent extends UserSettingsEvent {
const GetUserSettingsEvent();
}
@@ -20,9 +24,7 @@ class UpdateUserSettingsEvent extends UserSettingsEvent {
}

class GetUserBlocksEvent extends UserSettingsEvent {
final int? userId;

const GetUserBlocksEvent({this.userId});
const GetUserBlocksEvent();
}

class UnblockInstanceEvent extends UserSettingsEvent {
1 change: 1 addition & 0 deletions lib/user/bloc/user_settings_state.dart
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ enum UserSettingsStatus {
failure,
revert,
failedRevert,
notLoggedIn,
}

class UserSettingsState extends Equatable {
2 changes: 1 addition & 1 deletion lib/user/pages/user_page.dart
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ class _UserPageState extends State<UserPage> {
BlocProvider.value(value: accountBloc),
BlocProvider.value(value: thunderBloc),
],
child: UserSettingsPage(widget.userId),
child: const UserSettingsPage(),
),
),
);
323 changes: 167 additions & 156 deletions lib/user/pages/user_settings_page.dart

Large diffs are not rendered by default.

0 comments on commit f19c355

Please sign in to comment.