Compare commits

..
3 changed files with 66 additions and 92 deletions

View file

@ -1,5 +1,4 @@
import "dart:io"; import "dart:io";
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:material_ui/material_ui.dart"; import "package:material_ui/material_ui.dart";
import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:flutter_riverpod/flutter_riverpod.dart";
@ -9,7 +8,6 @@ import "package:nexus/controllers/account_data.dart";
import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/client.dart";
import "package:nexus/controllers/client_state.dart"; import "package:nexus/controllers/client_state.dart";
import "package:nexus/controllers/settings.dart"; import "package:nexus/controllers/settings.dart";
import "package:nexus/controllers/spec_versions.dart";
import "package:nexus/models/account_data.dart"; import "package:nexus/models/account_data.dart";
import "package:nexus/models/settings_category.dart"; import "package:nexus/models/settings_category.dart";
import "package:nexus/main.dart"; import "package:nexus/main.dart";
@ -20,6 +18,9 @@ class SettingsSectionsController
@override @override
Future<IMap<String, IList<SettingsCategory>>> build() async { Future<IMap<String, IList<SettingsCategory>>> build() async {
final settings = await ref.watch(SettingsController.provider.future); final settings = await ref.watch(SettingsController.provider.future);
final specVersionsResponse = await ref
.watch(ClientController.provider.notifier)
.getSpecVersions();
return .new({ return .new({
"General": .new([ "General": .new([
@ -48,7 +49,8 @@ class SettingsSectionsController
.new( .new(
title: "Use Dynamic Theme", title: "Use Dynamic Theme",
icon: Icons.palette, icon: Icons.palette,
description: "Toggle on or off Dynamic Theme. Only available on Android, Linux, Windows, or MacOS.", description:
"Toggle on or off Dynamic Theme. Only available on Android, Linux, Windows, or MacOS.",
builder: (title, description, icon) => SwitchListTile( builder: (title, description, icon) => SwitchListTile(
title: Text(title), title: Text(title),
subtitle: Text(description), subtitle: Text(description),
@ -74,7 +76,8 @@ class SettingsSectionsController
settings: .new([ settings: .new([
.new( .new(
title: "Linux Mobile Mode", title: "Linux Mobile Mode",
description: "Enables some fixes for Linux mobile, e.g. disabling dragging appbar for moving window.", description:
"Enables some fixes for Linux mobile, e.g. disabling dragging appbar for moving window.",
icon: Icons.construction, icon: Icons.construction,
builder: (title, description, icon) => SwitchListTile( builder: (title, description, icon) => SwitchListTile(
title: Text(title), title: Text(title),
@ -101,51 +104,40 @@ class SettingsSectionsController
settings: .new([ settings: .new([
.new( .new(
title: "Invite Blocking", title: "Invite Blocking",
description: "Block invites, either completely, or block only invites from users without shared private rooms (depends on server support).", description:
"Block invites, either completely, or block only invites from users without shared private rooms (depends on server support).",
builder: (title, description, icon) => Consumer( builder: (title, description, icon) => Consumer(
builder: (context, ref, _) { builder: (context, ref, _) =>
final specVersionsResponse = ref.watch( DialogListTile<DefaultInviteAction>(
SpecVersionsController.provider, icon: Icon(icon),
); title: title,
return DialogListTile<DefaultInviteAction>( subtitle: Text(description),
icon: Icon(icon), initialValue: ref
title: title, .watch(AccountDataController.provider)
subtitle: Text(description), .invitePermissionConfig
initialValue: ref .defaultAction,
.watch(AccountDataController.provider) options: specVersionsResponse.unstableFeatures.msc4494
.invitePermissionConfig ? DefaultInviteAction.values
.defaultAction, : IList(
options: DefaultInviteAction.values,
specVersionsResponse.maybeWhen( ).remove(.denyPublic).toList(),
data: (data) => data.unstableFeatures.msc4494, getName: (option) => switch (option) {
orElse: () => true, .allow => "Allow",
) .deny => "Deny",
? DefaultInviteAction.values .denyPublic => "Deny public",
: IList(DefaultInviteAction.values) },
.remove(.denyPublic) onChanged: (value) => ref
.toList(), .watch(ClientController.provider.notifier)
getName: (option) => switch (option) { .setAccountData(
.allow => "Allow", .new(
.deny => "Deny", type: AccountData.invitePermissionConfigKey,
.denyPublic => "Deny public", content: InvitePermissionConfig(
}, defaultAction: value,
onChanged: specVersionsResponse.maybeWhen( ),
data: (_) => ),
(value) => ref )
.watch(ClientController.provider.notifier) .onError(showError),
.setAccountData(
.new(
type: AccountData.invitePermissionConfigKey,
content: InvitePermissionConfig(
defaultAction: value,
),
),
)
.onError(showError),
orElse: () => null,
), ),
);
},
), ),
icon: Icons.person_off, icon: Icons.person_off,
), ),
@ -164,8 +156,9 @@ class SettingsSectionsController
final colorScheme = Theme.of(context).colorScheme; final colorScheme = Theme.of(context).colorScheme;
return M3EButton.icon( return M3EButton.icon(
onPressed: () async { onPressed: () async {
Navigator.of(context) Navigator.of(
.popUntil((route) => route.isFirst); context,
).popUntil((route) => route.isFirst);
await WidgetsBinding.instance.endOfFrame; await WidgetsBinding.instance.endOfFrame;

View file

@ -1,15 +0,0 @@
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/client.dart";
import "package:nexus/models/spec_versions_response.dart";
class SpecVersionsController extends AsyncNotifier<SpecVersionsResponse> {
@override
Future<SpecVersionsResponse> build() =>
ref.watch(ClientController.provider.notifier).getSpecVersions();
static final provider =
AsyncNotifierProvider.autoDispose<
SpecVersionsController,
SpecVersionsResponse
>(SpecVersionsController.new);
}

View file

@ -170,34 +170,30 @@ class const SettingsPage({super.key}) extends ConsumerWidget {
) )
: Row( : Row(
children: [ children: [
MaterialUiCompatibilityBridge( NavigationRailM3E(
child: NavigationRailM3E( type: .alwaysExpand,
type: .alwaysExpand, trailing: searchBar,
trailing: searchBar, scrollable: true,
scrollable: true, sections: sections
sections: sections .mapTo(
.mapTo( (categoryGroup, categories) =>
( NavigationRailM3ESection(
categoryGroup, header: DividerText(categoryGroup),
categories, destinations: categories
) => NavigationRailM3ESection( .map(
header: DividerText(categoryGroup), (category) =>
destinations: categories NavigationRailM3EDestination(
.map( icon: Icon(category.icon),
(category) => label: category.title,
NavigationRailM3EDestination( ),
icon: Icon(category.icon), )
label: category.title, .toList(),
), ),
) )
.toList(), .toList(),
), selectedIndex: selected.value,
) onDestinationSelected: (value) =>
.toList(), selected.value = value,
selectedIndex: selected.value,
onDestinationSelected: (value) =>
selected.value = value,
),
), ),
VerticalDivider(), VerticalDivider(),
Expanded( Expanded(