Skip to content

Commit 6357d3b

Browse files
committed
Port butterfly settings features to setonix
1 parent 608a383 commit 6357d3b

File tree

6 files changed

+193
-16
lines changed

6 files changed

+193
-16
lines changed

app/lib/bloc/settings.dart

+57-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,42 @@ import 'package:window_manager/window_manager.dart';
1010

1111
part 'settings.mapper.dart';
1212

13-
@MappableClass()
13+
@MappableEnum()
14+
enum ThemeDensity {
15+
system,
16+
maximize,
17+
desktop,
18+
compact,
19+
comfortable,
20+
standard;
21+
22+
VisualDensity toFlutter() => switch (this) {
23+
ThemeDensity.maximize =>
24+
const VisualDensity(horizontal: -4, vertical: -4),
25+
ThemeDensity.desktop =>
26+
const VisualDensity(horizontal: -3, vertical: -3),
27+
ThemeDensity.compact => VisualDensity.compact,
28+
ThemeDensity.comfortable => VisualDensity.comfortable,
29+
ThemeDensity.standard => VisualDensity.standard,
30+
ThemeDensity.system => VisualDensity.adaptivePlatformDensity,
31+
};
32+
}
33+
34+
final class ThemeModeMapper extends SimpleMapper<ThemeMode> {
35+
const ThemeModeMapper();
36+
37+
@override
38+
ThemeMode decode(Object value) {
39+
return ThemeMode.values.byName(value.toString());
40+
}
41+
42+
@override
43+
String encode(ThemeMode value) {
44+
return value.name;
45+
}
46+
}
47+
48+
@MappableClass(includeCustomMappers: [ThemeModeMapper()])
1449
class SetonixSettings with SetonixSettingsMappable implements LeapSettings {
1550
final String localeTag;
1651
final ThemeMode theme;
@@ -26,6 +61,7 @@ class SetonixSettings with SetonixSettingsMappable implements LeapSettings {
2661
final bool highContrast;
2762
final List<String> swamps;
2863
final double scrollSensitivity;
64+
final ThemeDensity density;
2965

3066
const SetonixSettings({
3167
this.localeTag = '',
@@ -41,6 +77,7 @@ class SetonixSettings with SetonixSettingsMappable implements LeapSettings {
4177
this.highContrast = false,
4278
this.zoom = 1,
4379
this.swamps = const [],
80+
this.density = ThemeDensity.system,
4481
this.scrollSensitivity = 1,
4582
});
4683

@@ -75,6 +112,9 @@ class SetonixSettings with SetonixSettingsMappable implements LeapSettings {
75112
zoom: prefs.getDouble('zoom') ?? 1,
76113
swamps: prefs.getStringList('swamps') ?? [],
77114
scrollSensitivity: prefs.getDouble('scrollSensitivity') ?? 1,
115+
density: ThemeDensity.values.byName(
116+
prefs.getString('density') ?? ThemeDensity.system.name,
117+
),
78118
);
79119

80120
Future<void> save() async {
@@ -100,6 +140,7 @@ class SetonixSettings with SetonixSettingsMappable implements LeapSettings {
100140
await prefs.setDouble('zoom', zoom);
101141
await prefs.setStringList('swamps', swamps);
102142
await prefs.setDouble('scrollSensitivity', scrollSensitivity);
143+
await prefs.setString('density', density.name);
103144
}
104145
}
105146

@@ -213,4 +254,19 @@ class SettingsCubit extends Cubit<SetonixSettings>
213254
emit(state.copyWith(scrollSensitivity: value));
214255
return save();
215256
}
257+
258+
Future<void> changeDensity(ThemeDensity value) {
259+
emit(state.copyWith(density: value));
260+
return save();
261+
}
262+
263+
Future<void> importSettings(String data) {
264+
final settings = SetonixSettingsMapper.fromJson(data);
265+
emit(settings);
266+
return state.save();
267+
}
268+
269+
Future<String> exportSettings() async {
270+
return state.toJson();
271+
}
216272
}

app/lib/bloc/settings.mapper.dart

+73
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,79 @@
66

77
part of 'settings.dart';
88

9+
class ThemeDensityMapper extends EnumMapper<ThemeDensity> {
10+
ThemeDensityMapper._();
11+
12+
static ThemeDensityMapper? _instance;
13+
static ThemeDensityMapper ensureInitialized() {
14+
if (_instance == null) {
15+
MapperContainer.globals.use(_instance = ThemeDensityMapper._());
16+
}
17+
return _instance!;
18+
}
19+
20+
static ThemeDensity fromValue(dynamic value) {
21+
ensureInitialized();
22+
return MapperContainer.globals.fromValue(value);
23+
}
24+
25+
@override
26+
ThemeDensity decode(dynamic value) {
27+
switch (value) {
28+
case r'system':
29+
return ThemeDensity.system;
30+
case r'maximize':
31+
return ThemeDensity.maximize;
32+
case r'desktop':
33+
return ThemeDensity.desktop;
34+
case r'compact':
35+
return ThemeDensity.compact;
36+
case r'comfortable':
37+
return ThemeDensity.comfortable;
38+
case r'standard':
39+
return ThemeDensity.standard;
40+
default:
41+
throw MapperException.unknownEnumValue(value);
42+
}
43+
}
44+
45+
@override
46+
dynamic encode(ThemeDensity self) {
47+
switch (self) {
48+
case ThemeDensity.system:
49+
return r'system';
50+
case ThemeDensity.maximize:
51+
return r'maximize';
52+
case ThemeDensity.desktop:
53+
return r'desktop';
54+
case ThemeDensity.compact:
55+
return r'compact';
56+
case ThemeDensity.comfortable:
57+
return r'comfortable';
58+
case ThemeDensity.standard:
59+
return r'standard';
60+
}
61+
}
62+
}
63+
64+
extension ThemeDensityMapperExtension on ThemeDensity {
65+
String toValue() {
66+
ThemeDensityMapper.ensureInitialized();
67+
return MapperContainer.globals.toValue<ThemeDensity>(this) as String;
68+
}
69+
}
70+
971
class SetonixSettingsMapper extends ClassMapperBase<SetonixSettings> {
1072
SetonixSettingsMapper._();
1173

1274
static SetonixSettingsMapper? _instance;
1375
static SetonixSettingsMapper ensureInitialized() {
1476
if (_instance == null) {
1577
MapperContainer.globals.use(_instance = SetonixSettingsMapper._());
78+
MapperContainer.globals.useAll([ThemeModeMapper()]);
1679
GamePropertyMapper.ensureInitialized();
1780
ListGameServerMapper.ensureInitialized();
81+
ThemeDensityMapper.ensureInitialized();
1882
}
1983
return _instance!;
2084
}
@@ -62,6 +126,9 @@ class SetonixSettingsMapper extends ClassMapperBase<SetonixSettings> {
62126
static List<String> _$swamps(SetonixSettings v) => v.swamps;
63127
static const Field<SetonixSettings, List<String>> _f$swamps =
64128
Field('swamps', _$swamps, opt: true, def: const []);
129+
static ThemeDensity _$density(SetonixSettings v) => v.density;
130+
static const Field<SetonixSettings, ThemeDensity> _f$density =
131+
Field('density', _$density, opt: true, def: ThemeDensity.system);
65132
static double _$scrollSensitivity(SetonixSettings v) => v.scrollSensitivity;
66133
static const Field<SetonixSettings, double> _f$scrollSensitivity =
67134
Field('scrollSensitivity', _$scrollSensitivity, opt: true, def: 1);
@@ -81,6 +148,7 @@ class SetonixSettingsMapper extends ClassMapperBase<SetonixSettings> {
81148
#highContrast: _f$highContrast,
82149
#zoom: _f$zoom,
83150
#swamps: _f$swamps,
151+
#density: _f$density,
84152
#scrollSensitivity: _f$scrollSensitivity,
85153
};
86154

@@ -99,6 +167,7 @@ class SetonixSettingsMapper extends ClassMapperBase<SetonixSettings> {
99167
highContrast: data.dec(_f$highContrast),
100168
zoom: data.dec(_f$zoom),
101169
swamps: data.dec(_f$swamps),
170+
density: data.dec(_f$density),
102171
scrollSensitivity: data.dec(_f$scrollSensitivity));
103172
}
104173

@@ -174,6 +243,7 @@ abstract class SetonixSettingsCopyWith<$R, $In extends SetonixSettings, $Out>
174243
bool? highContrast,
175244
double? zoom,
176245
List<String>? swamps,
246+
ThemeDensity? density,
177247
double? scrollSensitivity});
178248
SetonixSettingsCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(
179249
Then<$Out2, $R2> t);
@@ -214,6 +284,7 @@ class _SetonixSettingsCopyWithImpl<$R, $Out>
214284
bool? highContrast,
215285
double? zoom,
216286
List<String>? swamps,
287+
ThemeDensity? density,
217288
double? scrollSensitivity}) =>
218289
$apply(FieldCopyWithData({
219290
if (localeTag != null) #localeTag: localeTag,
@@ -229,6 +300,7 @@ class _SetonixSettingsCopyWithImpl<$R, $Out>
229300
if (highContrast != null) #highContrast: highContrast,
230301
if (zoom != null) #zoom: zoom,
231302
if (swamps != null) #swamps: swamps,
303+
if (density != null) #density: density,
232304
if (scrollSensitivity != null) #scrollSensitivity: scrollSensitivity
233305
}));
234306
@override
@@ -247,6 +319,7 @@ class _SetonixSettingsCopyWithImpl<$R, $Out>
247319
highContrast: data.get(#highContrast, or: $value.highContrast),
248320
zoom: data.get(#zoom, or: $value.zoom),
249321
swamps: data.get(#swamps, or: $value.swamps),
322+
density: data.get(#density, or: $value.density),
250323
scrollSensitivity:
251324
data.get(#scrollSensitivity, or: $value.scrollSensitivity));
252325

app/lib/l10n/app_en.arb

+6-1
Original file line numberDiff line numberDiff line change
@@ -244,5 +244,10 @@
244244
"inputs": "Inputs",
245245
"scroll": "Scroll",
246246
"sensitivity": "Sensitivity",
247-
"sensitivityHint": "The higher the value, the more sensitive the input"
247+
"sensitivityHint": "The higher the value, the more sensitive the input",
248+
"density": "Density",
249+
"desktop": "Desktop",
250+
"compact": "Compact",
251+
"standard": "Standard",
252+
"comfortable": "Comfortable"
248253
}

app/lib/pages/settings/personalization.dart

+41
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ class PersonalizationSettingsPage extends StatelessWidget {
2727
? LocaleNames.of(context)?.nameOf(locale.replaceAll('-', '_')) ?? locale
2828
: AppLocalizations.of(context).systemLocale;
2929

30+
String _getDensityName(BuildContext context, ThemeDensity density) =>
31+
switch (density) {
32+
ThemeDensity.system => AppLocalizations.of(context).systemTheme,
33+
ThemeDensity.maximize => LeapLocalizations.of(context).maximize,
34+
ThemeDensity.desktop => AppLocalizations.of(context).desktop,
35+
ThemeDensity.compact => AppLocalizations.of(context).compact,
36+
ThemeDensity.standard => AppLocalizations.of(context).standard,
37+
ThemeDensity.comfortable => AppLocalizations.of(context).comfortable,
38+
};
39+
3040
@override
3141
Widget build(BuildContext context) {
3242
return Scaffold(
@@ -74,6 +84,14 @@ class PersonalizationSettingsPage extends StatelessWidget {
7484
.comingSoon /*_getLocaleName(context, state.localeTag)*/),
7585
onTap: null /*() => _openLocaleModal(context)*/,
7686
),
87+
ListTile(
88+
leading:
89+
const PhosphorIcon(PhosphorIconsLight.gridNine),
90+
title: Text(AppLocalizations.of(context).density),
91+
subtitle:
92+
Text(_getDensityName(context, state.density)),
93+
onTap: () => _openDensityModal(context),
94+
),
7795
SwitchListTile(
7896
title:
7997
Text(AppLocalizations.of(context).highContrast),
@@ -113,6 +131,29 @@ class PersonalizationSettingsPage extends StatelessWidget {
113131
));
114132
}
115133

134+
void _openDensityModal(BuildContext context) {
135+
final cubit = context.read<SettingsCubit>();
136+
final density = cubit.state.density;
137+
138+
showLeapBottomSheet(
139+
context: context,
140+
titleBuilder: (ctx) => Text(AppLocalizations.of(context).density),
141+
childrenBuilder: (context) {
142+
void changeDensity(ThemeDensity density) {
143+
cubit.changeDensity(density);
144+
Navigator.of(context).pop();
145+
}
146+
147+
return ThemeDensity.values
148+
.map((e) => ListTile(
149+
title: Text(_getDensityName(context, e)),
150+
selected: e == density,
151+
onTap: () => changeDensity(e),
152+
))
153+
.toList();
154+
});
155+
}
156+
116157
void _openDesignModal(BuildContext context) {
117158
final cubit = context.read<SettingsCubit>();
118159
final design = cubit.state.design;

app/pubspec.lock

+14-14
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ packages:
1313
dependency: transitive
1414
description:
1515
name: analyzer
16-
sha256: f4c21c94eb4623b183c1014a470196b3910701bea9b926e6c91270d756e6fc60
16+
sha256: "13c1e6c6fd460522ea840abec3f677cc226f5fec7872c04ad7b425517ccf54f7"
1717
url: "https://pub.dev"
1818
source: hosted
19-
version: "7.4.1"
19+
version: "7.4.4"
2020
ansicolor:
2121
dependency: transitive
2222
description:
@@ -29,10 +29,10 @@ packages:
2929
dependency: "direct main"
3030
description:
3131
name: archive
32-
sha256: a7f37ff061d7abc2fcf213554b9dcaca713c5853afa5c065c44888bc9ccaf813
32+
sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd"
3333
url: "https://pub.dev"
3434
source: hosted
35-
version: "4.0.6"
35+
version: "4.0.7"
3636
args:
3737
dependency: transitive
3838
description:
@@ -278,10 +278,10 @@ packages:
278278
dependency: "direct main"
279279
description:
280280
name: device_info_plus
281-
sha256: "306b78788d1bb569edb7c55d622953c2414ca12445b41c9117963e03afc5c513"
281+
sha256: "0c6396126421b590089447154c5f98a5de423b70cfb15b1578fd018843ee6f53"
282282
url: "https://pub.dev"
283283
source: hosted
284-
version: "11.3.3"
284+
version: "11.4.0"
285285
device_info_plus_platform_interface:
286286
dependency: transitive
287287
description:
@@ -398,26 +398,26 @@ packages:
398398
dependency: "direct main"
399399
description:
400400
name: flame
401-
sha256: "0335f60d3fe81f1332c0ed424e8ac126dce3e94e56ceb105b734365f0d102b2a"
401+
sha256: f9e7a100c25f8d6bfd143bf325a9689c509216cd1c8133ce4684955c56770de7
402402
url: "https://pub.dev"
403403
source: hosted
404-
version: "1.28.0"
404+
version: "1.28.1"
405405
flame_bloc:
406406
dependency: "direct main"
407407
description:
408408
name: flame_bloc
409-
sha256: d238d64bd9776d52e29ca9be26ed1b6d8c043da32958e0dc74729c2bb8815afd
409+
sha256: "56a4dbbbe11b16ec391151f5bca72328a633abd54bd7325e0ba2fa4b687c3085"
410410
url: "https://pub.dev"
411411
source: hosted
412-
version: "1.12.11"
412+
version: "1.12.12"
413413
flame_tiled:
414414
dependency: "direct main"
415415
description:
416416
name: flame_tiled
417-
sha256: cc00796d32741a238f09d6d9cfbf985ff4bcfd11318b35086d7a36081ebe70eb
417+
sha256: "9b992ae10975ce3c6b4efe3dfba3c026ef21520e6d861c73707500b1b1481e78"
418418
url: "https://pub.dev"
419419
source: hosted
420-
version: "3.0.1"
420+
version: "3.0.2"
421421
flex_color_scheme:
422422
dependency: "direct main"
423423
description:
@@ -580,10 +580,10 @@ packages:
580580
dependency: "direct main"
581581
description:
582582
name: go_router
583-
sha256: "4cdfcc6a178632d1dbb7a728f8e84a1466211354704b9cdc03eee661d3277732"
583+
sha256: "2b9ba6d4c247457c35a6622f1dee6aab6694a4e15237ff7c32320345044112b6"
584584
url: "https://pub.dev"
585585
source: hosted
586-
version: "15.0.0"
586+
version: "15.1.1"
587587
graphs:
588588
dependency: transitive
589589
description:

0 commit comments

Comments
 (0)