refactor: уменьшил отступы от краев + сделал кастомизацию разворачиваемой

This commit is contained in:
Jganenokk
2026-07-11 16:27:37 +07:00
parent 4be18c0165
commit dfece96a5e
5 changed files with 178 additions and 213 deletions
+1 -1
View File
@@ -3897,7 +3897,7 @@ class _ChatScreenState extends State<ChatScreen>
final cs = Theme.of(context).colorScheme;
final accent = cs.primary;
return Padding(
padding: const EdgeInsets.fromLTRB(12, 8, 12, 6),
padding: const EdgeInsets.fromLTRB(8, 8, 8, 6),
child: Row(
children: [
Expanded(
@@ -1,187 +0,0 @@
import 'package:flutter/material.dart';
import 'package:material_symbols_icons/symbols.dart';
import '../../widgets/connection_status.dart';
import '../../../core/utils/haptics.dart';
import '../../widgets/glossy_pill.dart';
import 'app_icon_screen.dart';
import 'appearance_screen.dart';
import 'chat_background_screen.dart';
import 'font_settings_screen.dart';
import 'message_actions_screen.dart';
import 'theme_settings_screen.dart';
class _CustomizationCategory {
final IconData icon;
final String title;
final String subtitle;
final WidgetBuilder builder;
const _CustomizationCategory({
required this.icon,
required this.title,
required this.subtitle,
required this.builder,
});
}
class CustomizationScreen extends StatelessWidget {
const CustomizationScreen({super.key});
static const List<_CustomizationCategory> _categories = [
_CustomizationCategory(
icon: Symbols.dark_mode,
title: 'Тема',
subtitle: 'Светлая, тёмная, AMOLED, расписание',
builder: _buildThemeSettings,
),
_CustomizationCategory(
icon: Symbols.palette,
title: 'Внешний вид',
subtitle: 'Акцентный цвет интерфейса',
builder: _buildAppearance,
),
_CustomizationCategory(
icon: Symbols.wallpaper,
title: 'Фон чатов',
subtitle: 'Общие обои и темы для всех чатов',
builder: _buildChatBackground,
),
_CustomizationCategory(
icon: Symbols.text_fields,
title: 'Шрифты',
subtitle: 'Шрифт приложения, свои шрифты, размер текста',
builder: _buildFontSettings,
),
_CustomizationCategory(
icon: Symbols.touch_app,
title: 'Меню действий',
subtitle: 'Радиальное или список — для долгого нажатия на сообщение',
builder: _buildMessageActions,
),
_CustomizationCategory(
icon: Symbols.apps,
title: 'Иконка приложения',
subtitle: 'Default или Minimal — иконка на главном экране',
builder: _buildAppIcon,
),
];
static Widget _buildAppearance(BuildContext context) =>
const AppearanceScreen();
static Widget _buildChatBackground(BuildContext context) =>
const ChatBackgroundScreen();
static Widget _buildFontSettings(BuildContext context) =>
const FontSettingsScreen();
static Widget _buildThemeSettings(BuildContext context) =>
const ThemeSettingsScreen();
static Widget _buildMessageActions(BuildContext context) =>
const MessageActionsScreen();
static Widget _buildAppIcon(BuildContext context) => const AppIconScreen();
@override
Widget build(BuildContext context) {
final cs = Theme.of(context).colorScheme;
return Scaffold(
backgroundColor: cs.surface,
appBar: ConnectionTitleBar(
titleText: 'Кастомизация',
backgroundColor: cs.surface,
),
body: SafeArea(
top: false,
child: ListView(
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.fromLTRB(16, 12, 16, 120),
children: [
for (final category in _categories) ...[
_CategoryCard(
category: category,
onTap: () {
Haptics.tap();
Navigator.push(
context,
MaterialPageRoute(builder: category.builder),
);
},
),
const SizedBox(height: 12),
],
],
),
),
);
}
}
class _CategoryCard extends StatelessWidget {
final _CustomizationCategory category;
final VoidCallback onTap;
const _CategoryCard({required this.category, required this.onTap});
@override
Widget build(BuildContext context) {
final cs = Theme.of(context).colorScheme;
return GlossyPill(
color: cs.surfaceContainerHigh,
borderRadius: BorderRadius.circular(28),
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 18),
depth: 6,
onTap: onTap,
child: Row(
children: [
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: cs.primaryContainer,
shape: BoxShape.circle,
),
alignment: Alignment.center,
child: Icon(
category.icon,
color: cs.onPrimaryContainer,
size: 24,
weight: 500,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
category.title,
style: TextStyle(
color: cs.onSurface,
fontSize: 16,
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 3),
Text(
category.subtitle,
style: TextStyle(
color: cs.onSurfaceVariant,
fontSize: 13,
height: 1.3,
),
),
],
),
),
const SizedBox(width: 12),
Icon(Symbols.chevron_right, color: cs.outline, size: 22),
],
),
);
}
}
@@ -0,0 +1,170 @@
import 'package:flutter/material.dart';
import 'package:material_symbols_icons/symbols.dart';
import '../../../core/utils/haptics.dart';
import '../../widgets/glossy_pill.dart';
import '../../widgets/settings_card.dart';
import 'app_icon_screen.dart';
import 'appearance_screen.dart';
import 'chat_background_screen.dart';
import 'font_settings_screen.dart';
import 'message_actions_screen.dart';
import 'theme_settings_screen.dart';
class _CustomizationCategory {
final IconData icon;
final String title;
final WidgetBuilder builder;
const _CustomizationCategory({
required this.icon,
required this.title,
required this.builder,
});
}
class CustomizationSection extends StatefulWidget {
const CustomizationSection({super.key});
@override
State<CustomizationSection> createState() => _CustomizationSectionState();
}
class _CustomizationSectionState extends State<CustomizationSection> {
bool _expanded = false;
static final List<_CustomizationCategory> _categories = [
_CustomizationCategory(
icon: Symbols.dark_mode,
title: 'Тема',
builder: (context) => const ThemeSettingsScreen(),
),
_CustomizationCategory(
icon: Symbols.palette,
title: 'Внешний вид',
builder: (context) => const AppearanceScreen(),
),
_CustomizationCategory(
icon: Symbols.wallpaper,
title: 'Фон чатов',
builder: (context) => const ChatBackgroundScreen(),
),
_CustomizationCategory(
icon: Symbols.text_fields,
title: 'Шрифты',
builder: (context) => const FontSettingsScreen(),
),
_CustomizationCategory(
icon: Symbols.touch_app,
title: 'Меню действий',
builder: (context) => const MessageActionsScreen(),
),
_CustomizationCategory(
icon: Symbols.apps,
title: 'Иконка приложения',
builder: (context) => const AppIconScreen(),
),
];
void _toggle() {
Haptics.tap();
setState(() => _expanded = !_expanded);
}
void _open(_CustomizationCategory category) {
Haptics.tap();
Navigator.push(context, MaterialPageRoute(builder: category.builder));
}
@override
Widget build(BuildContext context) {
final cs = Theme.of(context).colorScheme;
return GlossyPill(
color: cs.surfaceContainerHigh,
borderRadius: BorderRadius.circular(20),
depth: 6,
child: Column(
children: [
_buildHeader(cs),
AnimatedSize(
duration: const Duration(milliseconds: 220),
curve: Curves.easeInOut,
alignment: Alignment.topCenter,
child: _expanded
? Column(children: _buildCategoryTiles(cs))
: const SizedBox(width: double.infinity),
),
],
),
);
}
Widget _buildHeader(ColorScheme cs) {
return Material(
color: Colors.transparent,
child: InkWell(
onTap: _toggle,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 17),
child: Row(
children: [
Icon(
Symbols.palette,
color: cs.onSurfaceVariant,
size: 22,
weight: 400,
),
const SizedBox(width: 16),
Expanded(
child: Text(
'Кастомизация',
style: TextStyle(
color: cs.onSurface,
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
),
AnimatedRotation(
duration: const Duration(milliseconds: 200),
turns: _expanded ? 0.5 : 0,
child: Icon(
Symbols.expand_more,
color: cs.outline,
size: 22,
weight: 400,
),
),
],
),
),
),
);
}
List<Widget> _buildCategoryTiles(ColorScheme cs) {
final tiles = <Widget>[];
for (var i = 0; i < _categories.length; i++) {
final category = _categories[i];
tiles.add(
Padding(
padding: const EdgeInsets.only(left: 58),
child: Divider(
height: 1,
thickness: 1,
color: cs.outlineVariant.withValues(alpha: 0.35),
),
),
);
tiles.add(
SettingsNavTile(
icon: category.icon,
label: category.title,
onTap: () => _open(category),
isLast: i == _categories.length - 1,
),
);
}
return tiles;
}
}
+4 -20
View File
@@ -26,7 +26,7 @@ import '../digital_id/digital_id_screen.dart';
import '../digital_id/digital_id_web_screen.dart';
import '../webapp/web_app_screen.dart';
import 'cloud_storage_screen.dart';
import 'customization_screen.dart';
import 'customization_section.dart';
import 'debug_menu_screen.dart';
import 'devices_screen.dart';
import 'edit_profile_screen.dart';
@@ -298,26 +298,10 @@ class _SettingsTabState extends State<SettingsTab> {
),
),
),
SliverToBoxAdapter(
const SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 12, 16, 0),
child: _buildSection(
context,
items: [
_SettingsItem(
icon: Symbols.palette,
label: 'Кастомизация',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CustomizationScreen(),
),
);
},
),
],
),
padding: EdgeInsets.fromLTRB(16, 12, 16, 0),
child: CustomizationSection(),
),
),
SliverToBoxAdapter(
+3 -5
View File
@@ -530,8 +530,8 @@ class MessageBubble extends StatelessWidget {
return Padding(
padding: EdgeInsets.only(
left: 12,
right: 12,
left: 8,
right: 8,
top: topMargin,
bottom: bottomMargin,
),
@@ -545,9 +545,7 @@ class MessageBubble extends StatelessWidget {
children: [
if (showAvatar)
_buildLeadingAvatar(cs)
else if (showAvatarSlot && chatType != "CHAT")
const SizedBox(width: 0)
else if (showAvatarSlot)
else if (showAvatarSlot && chatType == "CHAT")
const CircleAvatar(
radius: 15,
backgroundColor: Color(0x00000000),