feat: unified shell, diagnostics pack, native Office, sticky board
All checks were successful
CI / Windows build (push) Successful in 14m22s
All checks were successful
CI / Windows build (push) Successful in 14m22s
Make Surface remote debugging and classroom workflows viable: always-on structured logs with one-click zip export, a single AppShell chrome, OOXML PPTX/DOCX annotation without LibreOffice, and a first-class sticky board. Also drop spike/legacy ink widgets and tighten pen feel (predictor, PenInfoHistory, page-tile layer). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
110
lib/theme/app_theme.dart
Normal file
110
lib/theme/app_theme.dart
Normal file
@@ -0,0 +1,110 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
/// BadNote design tokens — ink-desk academic aesthetic.
|
||||
/// Warm paper field, graphite ink, single copper accent. No Inter / no purple.
|
||||
abstract final class AppTokens {
|
||||
static const Color paper = Color(0xFFF3EDE3);
|
||||
static const Color paperDark = Color(0xFF1C1A17);
|
||||
static const Color ink = Color(0xFF1F1B16);
|
||||
static const Color inkMuted = Color(0xFF6B6358);
|
||||
static const Color rule = Color(0xFFD9CFC0);
|
||||
static const Color copper = Color(0xFFB45A2A);
|
||||
static const Color copperSoft = Color(0xFFE8C4AE);
|
||||
static const Color sticky = Color(0xFFF6E7A5);
|
||||
|
||||
static const double radiusSm = 6;
|
||||
static const double radiusMd = 12;
|
||||
static const double chromePad = 16;
|
||||
}
|
||||
|
||||
abstract final class AppTheme {
|
||||
static ThemeData light() {
|
||||
final base = ColorScheme.fromSeed(
|
||||
seedColor: AppTokens.copper,
|
||||
brightness: Brightness.light,
|
||||
surface: AppTokens.paper,
|
||||
primary: AppTokens.copper,
|
||||
onPrimary: Colors.white,
|
||||
onSurface: AppTokens.ink,
|
||||
secondary: AppTokens.inkMuted,
|
||||
);
|
||||
return _build(base, Brightness.light);
|
||||
}
|
||||
|
||||
static ThemeData dark() {
|
||||
final base = ColorScheme.fromSeed(
|
||||
seedColor: AppTokens.copperSoft,
|
||||
brightness: Brightness.dark,
|
||||
surface: AppTokens.paperDark,
|
||||
primary: AppTokens.copperSoft,
|
||||
onSurface: AppTokens.paper,
|
||||
);
|
||||
return _build(base, Brightness.dark);
|
||||
}
|
||||
|
||||
static ThemeData fromScheme(ColorScheme scheme) =>
|
||||
_build(scheme, scheme.brightness);
|
||||
|
||||
static ThemeData _build(ColorScheme scheme, Brightness brightness) {
|
||||
final display = GoogleFonts.sourceSerif4TextTheme(
|
||||
ThemeData(brightness: brightness).textTheme,
|
||||
);
|
||||
final ui = GoogleFonts.ibmPlexSansTextTheme(
|
||||
ThemeData(brightness: brightness).textTheme,
|
||||
);
|
||||
final merged = ui.copyWith(
|
||||
displayLarge: display.displayLarge?.copyWith(fontWeight: FontWeight.w600),
|
||||
displayMedium: display.displayMedium?.copyWith(fontWeight: FontWeight.w600),
|
||||
displaySmall: display.displaySmall?.copyWith(fontWeight: FontWeight.w600),
|
||||
headlineLarge: display.headlineLarge?.copyWith(fontWeight: FontWeight.w600),
|
||||
headlineMedium: display.headlineMedium?.copyWith(fontWeight: FontWeight.w600),
|
||||
headlineSmall: display.headlineSmall?.copyWith(fontWeight: FontWeight.w600),
|
||||
titleLarge: display.titleLarge?.copyWith(fontWeight: FontWeight.w600),
|
||||
);
|
||||
|
||||
return ThemeData(
|
||||
useMaterial3: true,
|
||||
colorScheme: scheme,
|
||||
scaffoldBackgroundColor: scheme.surface,
|
||||
textTheme: merged,
|
||||
appBarTheme: AppBarTheme(
|
||||
centerTitle: false,
|
||||
backgroundColor: scheme.surface,
|
||||
foregroundColor: scheme.onSurface,
|
||||
elevation: 0,
|
||||
scrolledUnderElevation: 0.5,
|
||||
titleTextStyle: display.titleLarge?.copyWith(
|
||||
color: scheme.onSurface,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
navigationBarTheme: NavigationBarThemeData(
|
||||
backgroundColor: scheme.surface,
|
||||
indicatorColor: AppTokens.copper.withValues(alpha: 0.18),
|
||||
labelTextStyle: WidgetStatePropertyAll(
|
||||
ui.labelMedium?.copyWith(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
navigationRailTheme: NavigationRailThemeData(
|
||||
backgroundColor: scheme.surface,
|
||||
indicatorColor: AppTokens.copper.withValues(alpha: 0.18),
|
||||
selectedIconTheme: IconThemeData(color: scheme.primary),
|
||||
unselectedIconTheme: IconThemeData(color: scheme.onSurfaceVariant),
|
||||
),
|
||||
cardTheme: CardThemeData(
|
||||
color: scheme.surface,
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(AppTokens.radiusMd),
|
||||
side: BorderSide(color: AppTokens.rule.withValues(alpha: 0.7)),
|
||||
),
|
||||
),
|
||||
dividerColor: AppTokens.rule,
|
||||
floatingActionButtonTheme: FloatingActionButtonThemeData(
|
||||
backgroundColor: scheme.primary,
|
||||
foregroundColor: scheme.onPrimary,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user