fluffychat/lib/pages/settings_style/settings_style_view.dart
Marcus Hoffmann ccfa3fa8f6 feat: make showing user presence info optional
895de76e70 replaced the stories feature
with presence status messages. Stories were an optional feature but
right now presence information can only be disabled on a homeserver
level.

Introduce a setting to make this feature optional on a client level.
2024-02-11 20:21:13 +01:00

308 lines
14 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:fluffychat/config/setting_keys.dart';
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/utils/account_config.dart';
import 'package:fluffychat/widgets/avatar.dart';
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:fluffychat/widgets/mxc_image.dart';
import '../../config/app_config.dart';
import '../../widgets/settings_switch_list_tile.dart';
import 'settings_style.dart';
class SettingsStyleView extends StatelessWidget {
final SettingsStyleController controller;
const SettingsStyleView(this.controller, {super.key});
@override
Widget build(BuildContext context) {
const colorPickerSize = 32.0;
final client = Matrix.of(context).client;
return Scaffold(
appBar: AppBar(
leading: const Center(child: BackButton()),
title: Text(L10n.of(context)!.changeTheme),
),
backgroundColor: Theme.of(context).colorScheme.surface,
body: MaxWidthBody(
child: Column(
children: [
ListTile(
title: Text(
L10n.of(context)!.setColorTheme,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
),
SizedBox(
height: colorPickerSize + 24,
child: ListView(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children: SettingsStyleController.customColors
.map(
(color) => Padding(
padding: const EdgeInsets.all(12.0),
child: InkWell(
borderRadius: BorderRadius.circular(colorPickerSize),
onTap: () => controller.setChatColor(color),
child: color == null
? Material(
elevation: 6,
shadowColor: AppConfig.colorSchemeSeed,
borderRadius:
BorderRadius.circular(colorPickerSize),
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
colorPickerSize,
),
gradient: FluffyThemes.backgroundGradient(
context,
255,
),
),
child: SizedBox(
height: colorPickerSize,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
),
child: Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (controller.currentColor ==
null)
Padding(
padding:
const EdgeInsets.only(
right: 8.0,
),
child: Icon(
Icons.check,
size: 16,
color: Theme.of(context)
.colorScheme
.onBackground,
),
),
Text(
L10n.of(context)!.systemTheme,
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onBackground,
),
),
],
),
),
),
),
),
)
: Material(
color: color,
elevation: 6,
borderRadius:
BorderRadius.circular(colorPickerSize),
child: SizedBox(
width: colorPickerSize,
height: colorPickerSize,
child: controller.currentColor == color
? const Center(
child: Icon(
Icons.check,
size: 16,
color: Colors.white,
),
)
: null,
),
),
),
),
)
.toList(),
),
),
const SizedBox(height: 8),
const Divider(height: 1),
ListTile(
title: Text(
L10n.of(context)!.setTheme,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
),
RadioListTile<ThemeMode>(
groupValue: controller.currentTheme,
value: ThemeMode.system,
title: Text(L10n.of(context)!.systemTheme),
onChanged: controller.switchTheme,
),
RadioListTile<ThemeMode>(
groupValue: controller.currentTheme,
value: ThemeMode.light,
title: Text(L10n.of(context)!.lightTheme),
onChanged: controller.switchTheme,
),
RadioListTile<ThemeMode>(
groupValue: controller.currentTheme,
value: ThemeMode.dark,
title: Text(L10n.of(context)!.darkTheme),
onChanged: controller.switchTheme,
),
const Divider(height: 1),
ListTile(
title: Text(
L10n.of(context)!.presenceStyle,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
),
SettingsSwitchListTile.adaptive(
title: L10n.of(context)!.presencesToggle,
onChanged: (b) => AppConfig.showPresences = b,
storeKey: SettingKeys.showPresences,
defaultValue: AppConfig.showPresences,
),
const Divider(height: 1),
ListTile(
title: Text(
L10n.of(context)!.messagesStyle,
style: TextStyle(
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
),
StreamBuilder(
stream: client.onAccountData.stream.where(
(data) =>
data.type ==
ApplicationAccountConfigExtension.accountDataKey,
),
builder: (context, snapshot) {
final accountConfig = client.applicationAccountConfig;
final wallpaperOpacity = accountConfig.wallpaperOpacity ?? 1;
final wallpaperOpacityIsDefault = wallpaperOpacity == 1;
return Column(
mainAxisSize: MainAxisSize.min,
children: [
AnimatedContainer(
duration: FluffyThemes.animationDuration,
curve: FluffyThemes.animationCurve,
alignment: Alignment.centerLeft,
decoration: const BoxDecoration(),
clipBehavior: Clip.hardEdge,
child: Stack(
children: [
if (accountConfig.wallpaperUrl != null)
Opacity(
opacity: wallpaperOpacity,
child: MxcImage(
uri: accountConfig.wallpaperUrl,
fit: BoxFit.cover,
isThumbnail: true,
width: FluffyThemes.columnWidth * 2,
height: 156,
),
),
Padding(
padding: EdgeInsets.only(
left: 12 + 12 + Avatar.defaultSize,
right: 12,
top: accountConfig.wallpaperUrl == null ? 0 : 12,
bottom: 12,
),
child: Material(
color: Theme.of(context)
.colorScheme
.primaryContainer,
borderRadius: BorderRadius.circular(
AppConfig.borderRadius,
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
child: Text(
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor',
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onPrimaryContainer,
fontSize: AppConfig.messageFontSize *
AppConfig.fontSizeFactor,
),
),
),
),
),
],
),
),
ListTile(
title: Text(L10n.of(context)!.wallpaper),
leading: const Icon(Icons.photo_outlined),
trailing: accountConfig.wallpaperUrl == null
? null
: IconButton(
icon: const Icon(Icons.delete_outlined),
color: Theme.of(context).colorScheme.error,
onPressed: controller.deleteChatWallpaper,
),
onTap: controller.setWallpaper,
),
AnimatedSize(
duration: FluffyThemes.animationDuration,
curve: FluffyThemes.animationCurve,
child: accountConfig.wallpaperUrl != null
? SwitchListTile.adaptive(
title: Text(L10n.of(context)!.transparent),
secondary: const Icon(Icons.blur_linear_outlined),
value: !wallpaperOpacityIsDefault,
onChanged: (_) =>
controller.setChatWallpaperOpacity(
wallpaperOpacityIsDefault ? 0.4 : 1,
),
)
: null,
),
],
);
},
),
ListTile(
title: Text(L10n.of(context)!.fontSize),
trailing: Text('× ${AppConfig.fontSizeFactor}'),
),
Slider.adaptive(
min: 0.5,
max: 2.5,
divisions: 20,
value: AppConfig.fontSizeFactor,
semanticFormatterCallback: (d) => d.toString(),
onChanged: controller.changeFontSizeFactor,
),
],
),
),
);
}
}