Adapted settings to tablet
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
7
lib/screens/settings/model/settings.model.dart
Normal file
7
lib/screens/settings/model/settings.model.dart
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
class SettingsModel {
|
||||||
|
int? selectedScreen;
|
||||||
|
|
||||||
|
SettingsModel({
|
||||||
|
this.selectedScreen,
|
||||||
|
});
|
||||||
|
}
|
||||||
18
lib/screens/settings/provider/settings.provider.dart
Normal file
18
lib/screens/settings/provider/settings.provider.dart
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
25
lib/screens/settings/provider/settings.provider.g.dart
Normal file
25
lib/screens/settings/provider/settings.provider.g.dart
Normal 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
|
||||||
@@ -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));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
97
lib/widgets/custom_settings_tile.dart
Normal file
97
lib/widgets/custom_settings_tile.dart
Normal 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),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user