Skip to content

Commit aa97842

Browse files
committed
test(settings): Adapt BrowserPreference tests to FigmaToggle
1 parent ea7abd2 commit aa97842

File tree

2 files changed

+236
-96
lines changed

2 files changed

+236
-96
lines changed

lib/widgets/settings.dart

Lines changed: 131 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class FigmaToggle extends StatelessWidget {
3434
final theme = Theme.of(context);
3535
final colorScheme = theme.colorScheme;
3636

37-
// Figma-specified dimensions
37+
// Exact Figma-specified dimensions
3838
final trackWidth = value ? 48.0 : 46.0;
3939
final trackHeight = value ? 28.0 : 26.0;
4040
final thumbRadius = value ? 10.0 : 7.0;
@@ -48,6 +48,13 @@ class FigmaToggle extends StatelessWidget {
4848
final trackColor = value ? effectiveActiveColor : effectiveInactiveColor;
4949
final thumbColor = value ? effectiveActiveThumbColor : effectiveInactiveThumbColor;
5050

51+
// Calculate thumb positioning with proper padding
52+
final thumbDiameter = thumbRadius * 2;
53+
final horizontalPadding = 4.0;
54+
final thumbLeftPosition = value
55+
? trackWidth - thumbDiameter - horizontalPadding
56+
: horizontalPadding;
57+
5158
return GestureDetector(
5259
onTap: onChanged != null ? () => onChanged!(!value) : null,
5360
child: AnimatedContainer(
@@ -64,15 +71,13 @@ class FigmaToggle extends StatelessWidget {
6471
AnimatedPositioned(
6572
duration: const Duration(milliseconds: 200),
6673
curve: Curves.easeInOut,
67-
left: value
68-
? trackWidth - (thumbRadius * 2) - 4.0 // 4px padding from edge
69-
: 4.0, // 4px padding from edge
70-
top: (trackHeight - (thumbRadius * 2)) / 2,
74+
left: thumbLeftPosition,
75+
top: (trackHeight - thumbDiameter) / 2,
7176
child: AnimatedContainer(
7277
duration: const Duration(milliseconds: 200),
7378
curve: Curves.easeInOut,
74-
width: thumbRadius * 2,
75-
height: thumbRadius * 2,
79+
width: thumbDiameter,
80+
height: thumbDiameter,
7681
decoration: BoxDecoration(
7782
shape: BoxShape.circle,
7883
color: thumbColor,
@@ -105,26 +110,35 @@ class SettingsPage extends StatelessWidget {
105110

106111
static AccountRoute<void> buildRoute({required BuildContext context}) {
107112
return MaterialAccountWidgetRoute(
108-
context: context, page: const SettingsPage());
113+
context: context,
114+
page: const SettingsPage(),
115+
);
109116
}
110117

111118
@override
112119
Widget build(BuildContext context) {
113120
final zulipLocalizations = ZulipLocalizations.of(context);
114121
return Scaffold(
115122
appBar: ZulipAppBar(
116-
title: Text(zulipLocalizations.settingsPageTitle)),
117-
body: Column(children: [
118-
const _ThemeSetting(),
119-
const _BrowserPreferenceSetting(),
120-
const _VisitFirstUnreadSetting(),
121-
const _MarkReadOnScrollSetting(),
122-
if (GlobalSettingsStore.experimentalFeatureFlags.isNotEmpty)
123-
ListTile(
124-
title: Text(zulipLocalizations.experimentalFeatureSettingsPageTitle),
125-
onTap: () => Navigator.push(context,
126-
ExperimentalFeaturesPage.buildRoute()))
127-
]));
123+
title: Text(zulipLocalizations.settingsPageTitle),
124+
),
125+
body: Column(
126+
children: [
127+
const _ThemeSetting(),
128+
const _BrowserPreferenceSetting(),
129+
const _VisitFirstUnreadSetting(),
130+
const _MarkReadOnScrollSetting(),
131+
if (GlobalSettingsStore.experimentalFeatureFlags.isNotEmpty)
132+
ListTile(
133+
title: Text(zulipLocalizations.experimentalFeatureSettingsPageTitle),
134+
onTap: () => Navigator.push(
135+
context,
136+
ExperimentalFeaturesPage.buildRoute(),
137+
),
138+
),
139+
],
140+
),
141+
);
128142
}
129143
}
130144

@@ -147,14 +161,14 @@ class _ThemeSetting extends StatelessWidget {
147161
RadioListTile<ThemeSetting?>.adaptive(
148162
title: Text(ThemeSetting.displayName(
149163
themeSetting: themeSettingOption,
150-
zulipLocalizations: zulipLocalizations)),
164+
zulipLocalizations: zulipLocalizations,
165+
)),
151166
value: themeSettingOption,
152-
// TODO(#1545) stop using the deprecated members
153-
// ignore: deprecated_member_use
154167
groupValue: globalSettings.themeSetting,
155-
// ignore: deprecated_member_use
156-
onChanged: (newValue) => _handleChange(context, newValue)),
157-
]);
168+
onChanged: (newValue) => _handleChange(context, newValue),
169+
),
170+
],
171+
);
158172
}
159173
}
160174

@@ -165,7 +179,8 @@ class _BrowserPreferenceSetting extends StatelessWidget {
165179
final globalSettings = GlobalStoreWidget.settingsOf(context);
166180
globalSettings.setBrowserPreference(
167181
newOpenLinksWithInAppBrowser ? BrowserPreference.inApp
168-
: BrowserPreference.external);
182+
: BrowserPreference.external,
183+
);
169184
}
170185

171186
@override
@@ -194,9 +209,14 @@ class _VisitFirstUnreadSetting extends StatelessWidget {
194209
return ListTile(
195210
title: Text(zulipLocalizations.initialAnchorSettingTitle),
196211
subtitle: Text(VisitFirstUnreadSettingPage._valueDisplayName(
197-
globalSettings.visitFirstUnread, zulipLocalizations: zulipLocalizations)),
198-
onTap: () => Navigator.push(context,
199-
VisitFirstUnreadSettingPage.buildRoute()));
212+
globalSettings.visitFirstUnread,
213+
zulipLocalizations: zulipLocalizations,
214+
)),
215+
onTap: () => Navigator.push(
216+
context,
217+
VisitFirstUnreadSettingPage.buildRoute(),
218+
),
219+
);
200220
}
201221
}
202222

@@ -207,7 +227,8 @@ class VisitFirstUnreadSettingPage extends StatelessWidget {
207227
return MaterialWidgetRoute(page: const VisitFirstUnreadSettingPage());
208228
}
209229

210-
static String _valueDisplayName(VisitFirstUnreadSetting value, {
230+
static String _valueDisplayName(
231+
VisitFirstUnreadSetting value, {
211232
required ZulipLocalizations zulipLocalizations,
212233
}) {
213234
return switch (value) {
@@ -221,7 +242,7 @@ class VisitFirstUnreadSettingPage extends StatelessWidget {
221242
}
222243

223244
void _handleChange(BuildContext context, VisitFirstUnreadSetting? value) {
224-
if (value == null) return; // TODO(log); can this actually happen? how?
245+
if (value == null) return;
225246
final globalSettings = GlobalStoreWidget.settingsOf(context);
226247
globalSettings.setVisitFirstUnread(value);
227248
}
@@ -232,19 +253,28 @@ class VisitFirstUnreadSettingPage extends StatelessWidget {
232253
final globalSettings = GlobalStoreWidget.settingsOf(context);
233254
return Scaffold(
234255
appBar: AppBar(title: Text(zulipLocalizations.initialAnchorSettingTitle)),
235-
body: Column(children: [
236-
ListTile(title: Text(zulipLocalizations.initialAnchorSettingDescription)),
237-
for (final value in VisitFirstUnreadSetting.values)
238-
RadioListTile.adaptive(
239-
title: Text(_valueDisplayName(value,
240-
zulipLocalizations: zulipLocalizations)),
241-
value: value,
242-
// TODO(#1545) stop using the deprecated members
243-
// ignore: deprecated_member_use
256+
body: Column(
257+
children: [
258+
ListTile(title: Text(zulipLocalizations.initialAnchorSettingDescription)),
259+
RadioGroup<VisitFirstUnreadSetting>(
244260
groupValue: globalSettings.visitFirstUnread,
245-
// ignore: deprecated_member_use
246-
onChanged: (newValue) => _handleChange(context, newValue)),
247-
]));
261+
onChanged: (newValue) => _handleChange(context, newValue),
262+
child: Column(
263+
children: [
264+
for (final value in VisitFirstUnreadSetting.values)
265+
RadioListTile.adaptive(
266+
title: Text(_valueDisplayName(
267+
value,
268+
zulipLocalizations: zulipLocalizations,
269+
)),
270+
value: value,
271+
),
272+
],
273+
),
274+
),
275+
],
276+
),
277+
);
248278
}
249279
}
250280

@@ -258,9 +288,14 @@ class _MarkReadOnScrollSetting extends StatelessWidget {
258288
return ListTile(
259289
title: Text(zulipLocalizations.markReadOnScrollSettingTitle),
260290
subtitle: Text(MarkReadOnScrollSettingPage._valueDisplayName(
261-
globalSettings.markReadOnScroll, zulipLocalizations: zulipLocalizations)),
262-
onTap: () => Navigator.push(context,
263-
MarkReadOnScrollSettingPage.buildRoute()));
291+
globalSettings.markReadOnScroll,
292+
zulipLocalizations: zulipLocalizations,
293+
)),
294+
onTap: () => Navigator.push(
295+
context,
296+
MarkReadOnScrollSettingPage.buildRoute(),
297+
),
298+
);
264299
}
265300
}
266301

@@ -271,7 +306,8 @@ class MarkReadOnScrollSettingPage extends StatelessWidget {
271306
return MaterialWidgetRoute(page: const MarkReadOnScrollSettingPage());
272307
}
273308

274-
static String _valueDisplayName(MarkReadOnScrollSetting value, {
309+
static String _valueDisplayName(
310+
MarkReadOnScrollSetting value, {
275311
required ZulipLocalizations zulipLocalizations,
276312
}) {
277313
return switch (value) {
@@ -284,7 +320,8 @@ class MarkReadOnScrollSettingPage extends StatelessWidget {
284320
};
285321
}
286322

287-
static String? _valueDescription(MarkReadOnScrollSetting value, {
323+
static String? _valueDescription(
324+
MarkReadOnScrollSetting value, {
288325
required ZulipLocalizations zulipLocalizations,
289326
}) {
290327
return switch (value) {
@@ -296,7 +333,7 @@ class MarkReadOnScrollSettingPage extends StatelessWidget {
296333
}
297334

298335
void _handleChange(BuildContext context, MarkReadOnScrollSetting? value) {
299-
if (value == null) return; // TODO(log); can this actually happen? how?
336+
if (value == null) return;
300337
final globalSettings = GlobalStoreWidget.settingsOf(context);
301338
globalSettings.setMarkReadOnScroll(value);
302339
}
@@ -307,24 +344,35 @@ class MarkReadOnScrollSettingPage extends StatelessWidget {
307344
final globalSettings = GlobalStoreWidget.settingsOf(context);
308345
return Scaffold(
309346
appBar: AppBar(title: Text(zulipLocalizations.markReadOnScrollSettingTitle)),
310-
body: Column(children: [
311-
ListTile(title: Text(zulipLocalizations.markReadOnScrollSettingDescription)),
312-
for (final value in MarkReadOnScrollSetting.values)
313-
RadioListTile.adaptive(
314-
title: Text(_valueDisplayName(value,
315-
zulipLocalizations: zulipLocalizations)),
316-
subtitle: () {
317-
final result = _valueDescription(value,
318-
zulipLocalizations: zulipLocalizations);
319-
return result == null ? null : Text(result);
320-
}(),
321-
value: value,
322-
// TODO(#1545) stop using the deprecated members
323-
// ignore: deprecated_member_use
347+
body: Column(
348+
children: [
349+
ListTile(title: Text(zulipLocalizations.markReadOnScrollSettingDescription)),
350+
RadioGroup<MarkReadOnScrollSetting>(
324351
groupValue: globalSettings.markReadOnScroll,
325-
// ignore: deprecated_member_use
326-
onChanged: (newValue) => _handleChange(context, newValue)),
327-
]));
352+
onChanged: (newValue) => _handleChange(context, newValue),
353+
child: Column(
354+
children: [
355+
for (final value in MarkReadOnScrollSetting.values)
356+
RadioListTile.adaptive(
357+
title: Text(_valueDisplayName(
358+
value,
359+
zulipLocalizations: zulipLocalizations,
360+
)),
361+
subtitle: () {
362+
final result = _valueDescription(
363+
value,
364+
zulipLocalizations: zulipLocalizations,
365+
);
366+
return result == null ? null : Text(result);
367+
}(),
368+
value: value,
369+
),
370+
],
371+
),
372+
),
373+
],
374+
),
375+
);
328376
}
329377
}
330378

@@ -343,18 +391,23 @@ class ExperimentalFeaturesPage extends StatelessWidget {
343391
assert(flags.isNotEmpty);
344392
return Scaffold(
345393
appBar: AppBar(
346-
title: Text(zulipLocalizations.experimentalFeatureSettingsPageTitle)),
347-
body: Column(children: [
348-
ListTile(
349-
title: Text(zulipLocalizations.experimentalFeatureSettingsWarning)),
350-
for (final flag in flags)
394+
title: Text(zulipLocalizations.experimentalFeatureSettingsPageTitle),
395+
),
396+
body: Column(
397+
children: [
351398
ListTile(
352-
title: Text(flag.name), // no i18n; these are developer-facing settings
353-
trailing: FigmaToggle(
354-
value: globalSettings.getBool(flag),
355-
onChanged: (value) => globalSettings.setBool(flag, value),
356-
),
399+
title: Text(zulipLocalizations.experimentalFeatureSettingsWarning),
357400
),
358-
]));
401+
for (final flag in flags)
402+
ListTile(
403+
title: Text(flag.name), // no i18n; these are developer-facing settings
404+
trailing: FigmaToggle(
405+
value: globalSettings.getBool(flag),
406+
onChanged: (value) => globalSettings.setBool(flag, value),
407+
),
408+
),
409+
],
410+
),
411+
);
359412
}
360413
}

0 commit comments

Comments
 (0)