Skip to content

Commit

Permalink
refactor: misc lib's code refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Yaroslav Kuchmenko committed Oct 25, 2023
1 parent 0424a69 commit b37c6b5
Show file tree
Hide file tree
Showing 18 changed files with 479 additions and 292 deletions.
1 change: 1 addition & 0 deletions example/lib/screens/gallery/ios_developer_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class _IosDeveloperScreen extends State<IosDeveloperScreen> {
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(middle: Text('Developer')),
// TODO: usage of SafeArea causes blank left and right spacing in horizontal mode
child: SafeArea(
bottom: false,
child: SettingsList(
Expand Down
120 changes: 70 additions & 50 deletions lib/src/list/settings_list.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:settings_ui/src/sections/abstract_settings_section.dart';
import 'package:settings_ui/src/utils/exceptions.dart';
import 'package:settings_ui/src/utils/platform_utils.dart';
import 'package:settings_ui/src/utils/settings_theme.dart';
import 'package:settings_ui/src/utils/theme_provider.dart';
import 'package:settings_ui/src/utils/theme_providers/theme_provider.dart';

class SettingsList extends StatelessWidget {
class SettingsList extends StatefulWidget {
const SettingsList({
required this.sections,
this.shrinkWrap = false,
Expand All @@ -16,6 +17,7 @@ class SettingsList extends StatelessWidget {
this.contentPadding,
this.scrollController,
this.useSystemTheme = false,
this.wideScreenBreakpoint = 810,
Key? key,
}) : super(key: key);

Expand All @@ -28,31 +30,49 @@ class SettingsList extends StatelessWidget {
final List<AbstractSettingsSection> sections;
final ScrollController? scrollController;

/// Width of the screen from [MediaQuery]'s [Size]
/// at which the wide screen padding will be applied
final double wideScreenBreakpoint;

/// If true, some parameters will be applied from the system theme
/// instead of default values of package or values from [SettingsThemeData]
/// that is: backgroundColor, tileBackgroundColor
/// TODO add more
final bool useSystemTheme;

@override
Widget build(BuildContext context) {
DevicePlatform platform;
if (this.platform == null || this.platform == DevicePlatform.device) {
State<SettingsList> createState() => _SettingsListState();
}

class _SettingsListState extends State<SettingsList> {
late DevicePlatform platform;

@override
void didChangeDependencies() {
super.didChangeDependencies();
if (widget.platform == null || widget.platform == DevicePlatform.device) {
platform = PlatformUtils.detectPlatform(context);
} else {
platform = this.platform!;
platform = widget.platform!;
}
}

@override
Widget build(BuildContext context) {
final themeBrightness = _getThemeBrightness(context, platform);
final userDefinedTheme = themeBrightness == Brightness.dark
? widget.darkTheme
: widget.lightTheme;

final brightness = calculateBrightness(context, platform);
final themeData = ThemeProvider.getTheme(
context: context,
platform: platform,
brightness: brightness,
useSystemTheme: useSystemTheme,
brightness: themeBrightness,
useSystemTheme: widget.useSystemTheme,
).merge(
userDefinedSettingsTheme:
brightness == Brightness.dark ? darkTheme : lightTheme,
useSystemTheme: useSystemTheme);
userDefinedSettingsTheme: userDefinedTheme,
useSystemTheme: widget.useSystemTheme,
);

return Container(
color: themeData.settingsListBackground,
Expand All @@ -62,64 +82,64 @@ class SettingsList extends StatelessWidget {
themeData: themeData,
platform: platform,
child: ListView.builder(
controller: scrollController,
physics: physics,
shrinkWrap: shrinkWrap,
itemCount: sections.length,
padding: contentPadding ?? calculateDefaultPadding(platform, context),
controller: widget.scrollController,
physics: widget.physics,
shrinkWrap: widget.shrinkWrap,
itemCount: widget.sections.length,
padding:
widget.contentPadding ?? _getDefaultPadding(platform, context),
itemBuilder: (BuildContext context, int index) {
return sections[index];
return widget.sections[index];
},
),
),
);
}

EdgeInsets calculateDefaultPadding(
DevicePlatform platform, BuildContext context) {
if (MediaQuery.of(context).size.width > 810) {
double padding = (MediaQuery.of(context).size.width - 810) / 2;
switch (platform) {
case DevicePlatform.android:
case DevicePlatform.fuchsia:
case DevicePlatform.linux:
case DevicePlatform.iOS:
case DevicePlatform.macOS:
case DevicePlatform.windows:
return EdgeInsets.symmetric(horizontal: padding);
case DevicePlatform.web:
return EdgeInsets.symmetric(vertical: 20, horizontal: padding);
case DevicePlatform.device:
throw Exception(
'You can\'t use the DevicePlatform.device in this context. '
'Incorrect platform: SettingsList.calculateDefaultPadding',
);
default:
return EdgeInsets.symmetric(
horizontal: padding,
);
}
}
EdgeInsets _getDefaultPadding(
DevicePlatform platform,
BuildContext context,
) {
final mqSizeWidth = MediaQuery.sizeOf(context).width;
final isWideScreen = mqSizeWidth > widget.wideScreenBreakpoint;
double horizontalPaddingValue =
(mqSizeWidth - widget.wideScreenBreakpoint) / 2;

switch (platform) {
case DevicePlatform.android:
case DevicePlatform.fuchsia:
case DevicePlatform.linux:
case DevicePlatform.iOS:
case DevicePlatform.macOS:
case DevicePlatform.windows:
return const EdgeInsets.symmetric(vertical: 0);
return isWideScreen
? EdgeInsets.symmetric(
horizontal: horizontalPaddingValue,
)
: EdgeInsets.zero;
case DevicePlatform.web:
return const EdgeInsets.symmetric(vertical: 20);
return isWideScreen
? EdgeInsets.symmetric(
vertical: 20,
horizontal: horizontalPaddingValue,
)
: const EdgeInsets.symmetric(
vertical: 20,
);
case DevicePlatform.device:
throw Exception(
'You can\'t use the DevicePlatform.device in this context. '
'Incorrect platform: SettingsList.calculateDefaultPadding',
throw InvalidDevicePlatformDeviceUsage(
'SettingsList._getDefaultPadding',
);
}
}

Brightness calculateBrightness(
BuildContext context, DevicePlatform platform) {
Brightness _getThemeBrightness(
BuildContext context,
DevicePlatform platform,
) {
// final platformBrightness =
// View.of(context).platformDispatcher.platformBrightness;
// TODO: remove this deprecated Window usage whenever min dark SDK constraint is 3.0
final Brightness platformBrightness =
WidgetsBinding.instance.window.platformBrightness;
final materialBrightness = Theme.of(context).brightness;
Expand Down
23 changes: 15 additions & 8 deletions lib/src/sections/platforms/android_settings_section.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,13 @@ class AndroidSettingsSection extends StatelessWidget {

@override
Widget build(BuildContext context) {
return buildSectionBody(context);
}

Widget buildSectionBody(BuildContext context) {
final theme = SettingsTheme.of(context);

// TODO: usage of textScaleFactor requires documentation
final scaleFactor = MediaQuery.of(context).textScaleFactor;
final tileList = buildTileList();

if (title == null) {
return tileList;
return _IosTileList(tiles: tiles);
}

return Padding(
Expand All @@ -37,6 +34,7 @@ class AndroidSettingsSection extends StatelessWidget {
children: [
Padding(
padding: titlePadding ??
// TODO: move literals to file with theme constants
EdgeInsetsDirectional.only(
top: 24 * scaleFactor,
bottom: 10 * scaleFactor,
Expand All @@ -52,14 +50,23 @@ class AndroidSettingsSection extends StatelessWidget {
),
Container(
color: theme.themeData.settingsSectionBackground,
child: tileList,
child: _IosTileList(tiles: tiles),
),
],
),
);
}
}

class _IosTileList extends StatelessWidget {
final List<AbstractSettingsTile> tiles;

const _IosTileList({
required this.tiles,
});

Widget buildTileList() {
@override
Widget build(BuildContext context) {
return ListView.builder(
shrinkWrap: true,
itemCount: tiles.length,
Expand Down
36 changes: 26 additions & 10 deletions lib/src/sections/platforms/ios_settings_section.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:settings_ui/settings_ui.dart';
import 'package:settings_ui/src/tiles/platforms/ios_settings_tile.dart';
import 'package:settings_ui/src/tiles/platforms/ios_settings_tile_additional_info.dart';

class IOSSettingsSection extends StatelessWidget {
const IOSSettingsSection({
Expand All @@ -25,6 +25,7 @@ class IOSSettingsSection extends StatelessWidget {

return Padding(
padding: margin ??
// TODO: move literals to file with theme constants
EdgeInsets.only(
top: 14.0 * scaleFactor,
bottom: isLastNonDescriptive ? 27 * scaleFactor : 10 * scaleFactor,
Expand All @@ -38,11 +39,13 @@ class IOSSettingsSection extends StatelessWidget {
Padding(
padding: titlePadding ??
EdgeInsetsDirectional.only(
// TODO: move literals to file with theme constants
start: 18,
bottom: 5 * scaleFactor,
),
child: DefaultTextStyle(
key: const Key('ios_settings_section_title_style'),
// TODO: move literals to file with theme constants
style: TextStyle(
color: theme.themeData.sectionTitleColor,
// TODO: is this one hardcoded?
Expand All @@ -51,13 +54,22 @@ class IOSSettingsSection extends StatelessWidget {
child: title!,
),
),
buildTileList(),
_IosTileList(tiles: tiles),
],
),
);
}
}

class _IosTileList extends StatelessWidget {
final List<AbstractSettingsTile> tiles;

const _IosTileList({
required this.tiles,
});

Widget buildTileList() {
@override
Widget build(BuildContext context) {
return ListView.builder(
shrinkWrap: true,
itemCount: tiles.length,
Expand All @@ -68,26 +80,30 @@ class IOSSettingsSection extends StatelessWidget {

bool enableTop = false;

if (index == 0 ||
// TODO: document this large condition
final isTopBorderRadiusRequired = index == 0 ||
(index > 0 &&
tiles[index - 1] is SettingsTile &&
(tiles[index - 1] as SettingsTile).description != null)) {
(tiles[index - 1] as SettingsTile).description != null);
if (isTopBorderRadiusRequired) {
enableTop = true;
}

var enableBottom = false;

var isBottomBorderRadiusRequired = false;
// TODO: document this large condition
if (index == tiles.length - 1 ||
(index < tiles.length &&
tile is SettingsTile &&
(tile).description != null)) {
enableBottom = true;
isBottomBorderRadiusRequired = true;
}

final isDividerRequired = index != tiles.length - 1;

return IOSSettingsTileAdditionalInfo(
enableTopBorderRadius: enableTop,
enableBottomBorderRadius: enableBottom,
needToShowDivider: index != tiles.length - 1,
enableBottomBorderRadius: isBottomBorderRadiusRequired,
needToShowDivider: isDividerRequired,
child: tile,
);
},
Expand Down
16 changes: 14 additions & 2 deletions lib/src/sections/platforms/web_settings_section.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class WebSettingsSection extends StatelessWidget {
children: [
if (title != null)
Container(
// TODO: move literals to file with theme constants
height: 65 * scaleFactor,
padding: titlePadding ??
EdgeInsetsDirectional.only(
Expand All @@ -40,6 +41,7 @@ class WebSettingsSection extends StatelessWidget {
),
child: DefaultTextStyle(
style: TextStyle(
// TODO: move literals to file with theme constants
color: theme.themeData.titleTextColor,
fontSize: 15,
),
Expand All @@ -48,17 +50,27 @@ class WebSettingsSection extends StatelessWidget {
),
Card(
shape:
// TODO: move literals to file with theme constants
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
elevation: 4,
color: theme.themeData.settingsSectionBackground,
child: buildTileList(),
child: _WebTileList(tiles: tiles),
),
],
),
);
}
}

class _WebTileList extends StatelessWidget {
final List<AbstractSettingsTile> tiles;

Widget buildTileList() {
const _WebTileList({
required this.tiles,
});

@override
Widget build(BuildContext context) {
return ListView.separated(
shrinkWrap: true,
itemCount: tiles.length,
Expand Down
Loading

0 comments on commit b37c6b5

Please sign in to comment.