Adapted settings to tablet

This commit is contained in:
Juan Gilsanz Polo
2024-02-28 20:50:40 +01:00
parent d13e521481
commit 36b27839c7
9 changed files with 251 additions and 8 deletions

View File

@@ -6,7 +6,7 @@
/// Locales: 2 /// Locales: 2
/// Strings: 350 (175 per locale) /// Strings: 350 (175 per locale)
/// ///
/// Built on 2024-02-28 at 18:58 UTC /// Built on 2024-02-28 at 19:46 UTC
// coverage:ignore-file // coverage:ignore-file
// ignore_for_file: type=lint // ignore_for_file: type=lint

View File

@@ -2,8 +2,10 @@ import 'package:flutter/material.dart';
class CustomizationModel { class CustomizationModel {
ScrollController? scrollController; ScrollController? scrollController;
int? selectedScreen;
CustomizationModel({ CustomizationModel({
this.scrollController, this.scrollController,
this.selectedScreen,
}); });
} }

View File

@@ -0,0 +1,7 @@
class SettingsModel {
int? selectedScreen;
SettingsModel({
this.selectedScreen,
});
}

View File

@@ -0,0 +1,18 @@
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:linkdy/screens/settings/model/settings.model.dart';
part 'settings.provider.g.dart';
@riverpod
class Settings extends _$Settings {
@override
SettingsModel build() {
return SettingsModel();
}
void setSelectedScreen(int screen) {
state.selectedScreen = screen;
ref.notifyListeners();
}
}

View File

@@ -0,0 +1,25 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'settings.provider.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$settingsHash() => r'709696bfa70c1fa702132beb428561e073c7a620';
/// See also [Settings].
@ProviderFor(Settings)
final settingsProvider =
AutoDisposeNotifierProvider<Settings, SettingsModel>.internal(
Settings.new,
name: r'settingsProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product') ? null : _$settingsHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef _$Settings = AutoDisposeNotifier<SettingsModel>;
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -2,21 +2,50 @@ import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_split_view/flutter_split_view.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:linkdy/providers/router.provider.dart';
import 'package:linkdy/router/paths.dart';
import 'package:linkdy/screens/settings/ui/customization/customization.dart';
import 'package:linkdy/screens/settings/provider/settings.provider.dart';
import 'package:linkdy/screens/settings/ui/general_settings/general_settings.dart';
import 'package:linkdy/widgets/section_label.dart'; import 'package:linkdy/widgets/section_label.dart';
import 'package:linkdy/widgets/custom_list_tile.dart'; import 'package:linkdy/widgets/custom_list_tile.dart';
import 'package:linkdy/widgets/custom_settings_tile.dart';
import 'package:linkdy/providers/app_info.provider.dart'; import 'package:linkdy/providers/app_info.provider.dart';
import 'package:linkdy/utils/open_url.dart'; import 'package:linkdy/utils/open_url.dart';
import 'package:linkdy/constants/strings.dart'; import 'package:linkdy/constants/strings.dart';
import 'package:linkdy/config/sizes.dart';
import 'package:linkdy/constants/urls.dart'; import 'package:linkdy/constants/urls.dart';
import 'package:linkdy/i18n/strings.g.dart'; import 'package:linkdy/i18n/strings.g.dart';
class SettingsScreen extends ConsumerWidget { class SettingsScreen extends ConsumerWidget {
const SettingsScreen({Key? key}) : super(key: key); const SettingsScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > Sizes.tabletBreakpoint) {
return const SplitView.material(
hideDivider: true,
flexWidth: FlexWidth(mainViewFlexWidth: 1, secondaryViewFlexWidth: 2),
child: _List(tabletView: true),
);
} else {
return const _List(tabletView: false);
}
},
);
}
}
class _List extends ConsumerWidget {
final bool tabletView;
const _List({
required this.tabletView,
});
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
@@ -27,17 +56,21 @@ class SettingsScreen extends ConsumerWidget {
body: ListView( body: ListView(
children: [ children: [
SectionLabel(label: t.settings.appSettings), SectionLabel(label: t.settings.appSettings),
CustomListTile( _SettingsTile(
icon: Icons.palette_rounded, icon: Icons.palette_rounded,
title: t.settings.customization.customization, title: t.settings.customization.customization,
subtitle: t.settings.customization.customizationDescription, subtitle: t.settings.customization.customizationDescription,
onTap: () => ref.read(routerProvider).push(RoutesPaths.customization), thisItem: 0,
twoColumns: tabletView,
screenToNavigate: const Customization(),
), ),
CustomListTile( _SettingsTile(
icon: Icons.settings_rounded, icon: Icons.settings_rounded,
title: t.settings.generalSettings.generalSettings, title: t.settings.generalSettings.generalSettings,
subtitle: t.settings.generalSettings.generalSettingsDescription, subtitle: t.settings.generalSettings.generalSettingsDescription,
onTap: () => ref.read(routerProvider).push(RoutesPaths.generalSettings), thisItem: 1,
screenToNavigate: const GeneralSettings(),
twoColumns: tabletView,
), ),
SectionLabel(label: t.settings.aboutApp), SectionLabel(label: t.settings.aboutApp),
CustomListTile( CustomListTile(
@@ -82,3 +115,51 @@ class SettingsScreen extends ConsumerWidget {
); );
} }
} }
class _SettingsTile extends ConsumerWidget {
final String title;
final String subtitle;
final IconData icon;
final Widget? trailing;
final Widget screenToNavigate;
final int thisItem;
final bool twoColumns;
const _SettingsTile({
required this.title,
required this.subtitle,
required this.icon,
this.trailing,
required this.screenToNavigate,
required this.thisItem,
required this.twoColumns,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
if (twoColumns) {
return CustomSettingsTile(
title: title,
subtitle: subtitle,
icon: icon,
trailing: trailing,
thisItem: thisItem,
selectedItem: ref.watch(settingsProvider).selectedScreen,
onTap: () {
ref.read(settingsProvider.notifier).setSelectedScreen(thisItem);
SplitView.of(context).setSecondary(screenToNavigate);
},
);
} else {
return CustomListTile(
title: title,
subtitle: subtitle,
icon: icon,
trailing: trailing,
onTap: () {
Navigator.of(context, rootNavigator: true).push(MaterialPageRoute(builder: (context) => screenToNavigate));
},
);
}
}
}

View File

@@ -0,0 +1,97 @@
import 'package:flutter/material.dart';
class CustomSettingsTile extends StatelessWidget {
final String title;
final String? subtitle;
final Widget? subtitleWidget;
final void Function()? onTap;
final IconData? icon;
final Widget? trailing;
final EdgeInsets? padding;
final int thisItem;
final int? selectedItem;
const CustomSettingsTile({
super.key,
required this.title,
this.subtitle,
this.subtitleWidget,
this.onTap,
this.icon,
this.trailing,
this.padding,
required this.thisItem,
required this.selectedItem,
});
@override
Widget build(BuildContext context) {
Widget tileBody = Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (icon != null) ...[
Icon(
icon,
size: 24,
color: Theme.of(context).listTileTheme.iconColor,
),
const SizedBox(width: 16),
],
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Theme.of(context).colorScheme.onSurface,
),
),
if (subtitle != null || subtitleWidget != null) ...[
const SizedBox(height: 5),
if (subtitle == null && subtitleWidget != null) subtitleWidget!,
if (subtitle != null && subtitleWidget == null)
Text(
subtitle!,
style: TextStyle(
color: Theme.of(context).listTileTheme.textColor,
fontSize: 14,
fontWeight: FontWeight.w400),
),
]
],
),
)
],
),
),
if (trailing != null) ...[const SizedBox(width: 10), trailing!]
],
);
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Material(
color: Colors.transparent,
borderRadius: BorderRadius.circular(28),
child: InkWell(
borderRadius: BorderRadius.circular(28),
onTap: onTap,
child: Container(
width: double.maxFinite,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(28),
color: thisItem == selectedItem ? Theme.of(context).colorScheme.primaryContainer : null),
child: tileBody),
),
),
);
}
}

View File

@@ -443,6 +443,15 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.1" version: "3.0.1"
flutter_split_view:
dependency: "direct main"
description:
path: "."
ref: master-alt
resolved-ref: a6aa2419243cc0abccf9474ce340790d6c0ded6f
url: "https://github.com/JGeek00/flutter_split_view"
source: git
version: "0.1.2"
flutter_svg: flutter_svg:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@@ -59,6 +59,10 @@ dependencies:
webview_flutter: ^4.7.0 webview_flutter: ^4.7.0
flutter_hooks: ^0.20.5 flutter_hooks: ^0.20.5
hooks_riverpod: ^2.4.10 hooks_riverpod: ^2.4.10
flutter_split_view:
git:
url: https://github.com/JGeek00/flutter_split_view
ref: master-alt
dev_dependencies: dev_dependencies:
build_runner: ^2.4.8 build_runner: ^2.4.8