Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"change": "App category rows keep the name and rating visible at larger text sizes"
}
34 changes: 27 additions & 7 deletions app/lib/pages/apps/widgets/category_section.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,44 @@ class CategorySection extends StatelessWidget {
final displayedApps = apps.take(9).toList();

// --- Configuration Constants ---
// Heights follow the reader's text size: fixed 85 / 60 pt rows cut the app's name, category
// and rating (and the section title) at a larger text size (layout lint, 1.3x).
// Heights follow the reader's text size. OmiType leaves `height` unset, so painted text
// inherits Material's line height (~1.43). Measuring the raw style misses that and the
// name/category/rating column overflows (13px at 1.3x on a 390pt-wide phone).
final scaler = MediaQuery.textScalerOf(context);
final direction = Directionality.of(context);
final inherited = DefaultTextStyle.of(context).style;
double lineOf(TextStyle style) {
final painter =
TextPainter(text: TextSpan(text: 'Ag', style: style), textScaler: scaler, textDirection: direction)..layout();
final painter = TextPainter(
text: TextSpan(text: 'Ag', style: inherited.merge(style)),
textScaler: scaler,
textDirection: direction,
maxLines: 1,
)..layout();
final height = painter.height;
painter.dispose();
return height;
}

final rowText = lineOf(OmiType.body) + 2 + lineOf(OmiType.footnote) + 2 + lineOf(OmiType.caption);
final double targetItemHeight = max(85.0, 16 + max(52.0, rowText) + 1);
final rowText = lineOf(OmiType.body.copyWith(fontWeight: FontWeight.w500)) +
2 +
lineOf(OmiType.footnote) +
2 +
lineOf(OmiType.caption);
const double cardVerticalPadding = 16;
const double artworkExtent = 60;
// Compact actions paint at 36pt and pad their tap target out to 48pt.
const double actionExtent = 48;
final double targetItemHeight = max(
85.0,
cardVerticalPadding + max(artworkExtent, max(actionExtent, rowText)) + 1,
);
const double crossAxisSpacing = 0.0;
const double mainAxisSpacing = 14.0;
const int maxRows = 3;
final double titleSectionHeight = max(60.0, 24 + 16 + lineOf(OmiType.title2));
final titleLine = lineOf(OmiType.title3);
final allChip = lineOf(OmiType.caption.copyWith(fontWeight: FontWeight.w600)) + 4;
final headerRow = max(titleLine, max(allChip, 16.0));
final double titleSectionHeight = max(60.0, 24 + 16 + headerRow);

// --- Dynamic Calculation ---
final int numRows = min(maxRows, displayedApps.length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,12 @@ void main() {
expect(service.connectionFor(device.id), same(connection));
expect(connection.status, DeviceConnectionState.disconnected);

// Later native event brings the device back in range
// Later native event brings the device back in range. Production transports
// (and this fake) use an asynchronous broadcast stream, so the connection
// applies the event on a later microtask — the same delivery ensureConnection
// sees after the event loop turns.
transport.emitConnected();
await pumpEventQueue();
expect(connection.status, DeviceConnectionState.connected);

// When connection is up, ensureConnection cleanly returns the existing connection
Expand Down
9 changes: 8 additions & 1 deletion app/test/widgets/apps_category_section_large_text_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:omi/l10n/app_localizations.dart';
import 'package:omi/pages/apps/providers/add_app_provider.dart';
import 'package:omi/pages/apps/widgets/category_section.dart';
import 'package:omi/providers/app_provider.dart';
import 'package:omi/ui/ui.dart';
import 'package:omi/utils/platform/platform_manager.dart';

// Regression test for #19238: CategorySection rows overflow at larger text sizes
Expand Down Expand Up @@ -110,7 +111,13 @@ void main() {
isNull,
reason: 'CategorySection should not overflow at scale on width ',
);
expect(find.text('Productivity'), findsOneWidget);
expect(
find.byWidgetPredicate(
(widget) =>
widget is Text && widget.data == 'Productivity' && widget.style?.fontSize == OmiType.title3.fontSize,
),
findsOneWidget,
);
expect(find.text('Productivity Booster Pro'), findsOneWidget);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ void main() {
isNull,
reason: 'AI app generator suggestion strip should not overflow at scale $scale on width $testWidth',
);
expect(find.text('Try something like'), findsOneWidget);
expect(find.text('Try something like…'), findsOneWidget);
expect(find.text('A playful gratitude spinner for daily positivity'), findsOneWidget);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:omi/l10n/app_localizations.dart';
import 'package:omi/pages/settings/settings_drawer.dart';
import 'package:omi/providers/app_provider.dart';
import 'package:omi/providers/home_provider.dart';
import 'package:omi/providers/usage_provider.dart';
import 'package:omi/providers/user_provider.dart';
import 'package:omi/ui/ui.dart';
import 'package:omi/utils/platform/platform_manager.dart';
Expand All @@ -23,6 +24,7 @@ Widget _buildHarness() {
ChangeNotifierProvider<AppProvider>.value(value: AppProvider()),
ChangeNotifierProvider<HomeProvider>.value(value: HomeProvider()),
ChangeNotifierProvider<UserProvider>.value(value: UserProvider()),
ChangeNotifierProvider<UsageProvider>(create: (_) => UsageProvider()),
],
child: const MaterialApp(
localizationsDelegates: [
Expand Down
Loading