mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor: use dependency injection to adapt the theme on mobile. (#3957)
This commit is contained in:
@ -1,275 +0,0 @@
|
|||||||
// ThemeData in mobile
|
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
|
||||||
import 'package:flowy_infra/colorscheme/colorscheme.dart';
|
|
||||||
import 'package:flowy_infra/size.dart';
|
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
|
||||||
|
|
||||||
const _primaryColor = Color(0xFF2DA2F6); //primary 100
|
|
||||||
const _onBackgroundColor = Color(0xff2F3030); // text/title color
|
|
||||||
const _onSurfaceColor = Color(0xff676666); // text/body color
|
|
||||||
const _onSecondaryColor = Color(0xFFC5C7CB); // text/body2 color
|
|
||||||
|
|
||||||
// TODO(yijing): improve theme color before release
|
|
||||||
ThemeData getMobileThemeData(
|
|
||||||
Brightness brightness,
|
|
||||||
FlowyColorScheme theme,
|
|
||||||
String fontFamily,
|
|
||||||
String monospaceFontFamily,
|
|
||||||
) {
|
|
||||||
fontFamily = GoogleFonts.getFont(fontFamily).fontFamily ?? fontFamily;
|
|
||||||
|
|
||||||
final mobileColorTheme = (brightness == Brightness.light)
|
|
||||||
? ColorScheme(
|
|
||||||
brightness: brightness,
|
|
||||||
primary: _primaryColor,
|
|
||||||
onPrimary: Colors.white,
|
|
||||||
// TODO(yijing): add color later
|
|
||||||
secondary: Colors.white,
|
|
||||||
onSecondary: _onSecondaryColor,
|
|
||||||
error: const Color(0xffFB006D),
|
|
||||||
onError: const Color(0xffFB006D),
|
|
||||||
background: Colors.white,
|
|
||||||
onBackground: _onBackgroundColor,
|
|
||||||
outline: const Color(0xffBDC0C5), //caption
|
|
||||||
outlineVariant: const Color(0xffCBD5E0).withOpacity(0.24),
|
|
||||||
//Snack bar
|
|
||||||
surface: Colors.white,
|
|
||||||
onSurface: _onSurfaceColor, // text/body color
|
|
||||||
surfaceVariant: const Color.fromARGB(255, 216, 216, 216),
|
|
||||||
)
|
|
||||||
: ColorScheme(
|
|
||||||
brightness: brightness,
|
|
||||||
primary: _primaryColor,
|
|
||||||
onPrimary: Colors.white,
|
|
||||||
// TODO(yijing): add color later
|
|
||||||
secondary: Colors.black,
|
|
||||||
onSecondary: Colors.white,
|
|
||||||
error: const Color(0xffFB006D),
|
|
||||||
onError: const Color(0xffFB006D),
|
|
||||||
background: const Color(0xff1C1C1E), // BG/Secondary color
|
|
||||||
onBackground: Colors.white,
|
|
||||||
outline: const Color(0xff96989C), //caption
|
|
||||||
outlineVariant: Colors.black,
|
|
||||||
//Snack bar
|
|
||||||
surface: const Color(0xff2F3030),
|
|
||||||
onSurface: const Color(0xffC5C6C7), // text/body color
|
|
||||||
);
|
|
||||||
|
|
||||||
return ThemeData(
|
|
||||||
// color
|
|
||||||
primaryColor: mobileColorTheme.primary, //primary 100
|
|
||||||
primaryColorLight: const Color(0xFF57B5F8), //primary 80
|
|
||||||
dividerColor: mobileColorTheme.outline, //caption
|
|
||||||
hintColor: mobileColorTheme.outline,
|
|
||||||
disabledColor: mobileColorTheme.outline,
|
|
||||||
scaffoldBackgroundColor: mobileColorTheme.background,
|
|
||||||
appBarTheme: AppBarTheme(
|
|
||||||
foregroundColor: mobileColorTheme.onBackground,
|
|
||||||
backgroundColor: mobileColorTheme.background,
|
|
||||||
centerTitle: false,
|
|
||||||
titleTextStyle: TextStyle(
|
|
||||||
color: mobileColorTheme.onBackground,
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
letterSpacing: 0.05,
|
|
||||||
),
|
|
||||||
shadowColor: mobileColorTheme.outlineVariant,
|
|
||||||
),
|
|
||||||
radioTheme: RadioThemeData(
|
|
||||||
fillColor: MaterialStateProperty.resolveWith((states) {
|
|
||||||
if (states.contains(MaterialState.selected)) {
|
|
||||||
return mobileColorTheme.primary;
|
|
||||||
}
|
|
||||||
return mobileColorTheme.outline;
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
// button
|
|
||||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
|
||||||
style: ButtonStyle(
|
|
||||||
fixedSize: MaterialStateProperty.all(const Size.fromHeight(48)),
|
|
||||||
elevation: MaterialStateProperty.all(0),
|
|
||||||
textStyle: MaterialStateProperty.all(
|
|
||||||
const TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
shadowColor: MaterialStateProperty.all(null),
|
|
||||||
backgroundColor: MaterialStateProperty.resolveWith<Color>(
|
|
||||||
(Set<MaterialState> states) {
|
|
||||||
if (states.contains(MaterialState.disabled)) {
|
|
||||||
return const Color(0xFF57B5F8);
|
|
||||||
}
|
|
||||||
return mobileColorTheme.primary;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
outlinedButtonTheme: OutlinedButtonThemeData(
|
|
||||||
style: ButtonStyle(
|
|
||||||
textStyle: MaterialStateProperty.all(
|
|
||||||
const TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
foregroundColor: MaterialStateProperty.all(
|
|
||||||
mobileColorTheme.onBackground,
|
|
||||||
),
|
|
||||||
backgroundColor: MaterialStateProperty.all(mobileColorTheme.background),
|
|
||||||
shape: MaterialStateProperty.all(
|
|
||||||
RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(6),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
side: MaterialStateProperty.all(
|
|
||||||
BorderSide(
|
|
||||||
color: mobileColorTheme.outline,
|
|
||||||
width: 0.5,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
padding: MaterialStateProperty.all(
|
|
||||||
const EdgeInsets.symmetric(horizontal: 8, vertical: 12),
|
|
||||||
),
|
|
||||||
// splash color
|
|
||||||
overlayColor: MaterialStateProperty.all(
|
|
||||||
Colors.grey[100],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
textButtonTheme: TextButtonThemeData(
|
|
||||||
style: ButtonStyle(
|
|
||||||
textStyle: MaterialStateProperty.all(
|
|
||||||
TextStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// text
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
textTheme: TextTheme(
|
|
||||||
displayLarge: const TextStyle(
|
|
||||||
color: Color(0xFF57B5F8),
|
|
||||||
fontSize: 32,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
height: 1.20,
|
|
||||||
letterSpacing: 0.16,
|
|
||||||
),
|
|
||||||
displayMedium: TextStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
color: mobileColorTheme.onBackground,
|
|
||||||
fontSize: 32,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
height: 1.20,
|
|
||||||
letterSpacing: 0.16,
|
|
||||||
),
|
|
||||||
// H1 Semi 26
|
|
||||||
displaySmall: TextStyle(
|
|
||||||
color: mobileColorTheme.onBackground,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
height: 1.10,
|
|
||||||
letterSpacing: 0.13,
|
|
||||||
),
|
|
||||||
// body2 14 Regular
|
|
||||||
bodyMedium: TextStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
color: mobileColorTheme.onBackground,
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
height: 1.20,
|
|
||||||
letterSpacing: 0.07,
|
|
||||||
),
|
|
||||||
// Trash empty title
|
|
||||||
labelLarge: TextStyle(
|
|
||||||
color: mobileColorTheme.onBackground,
|
|
||||||
fontSize: 22,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
letterSpacing: -0.3,
|
|
||||||
),
|
|
||||||
// setting item title
|
|
||||||
labelMedium: TextStyle(
|
|
||||||
color: mobileColorTheme.onSurface,
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
// setting group title
|
|
||||||
labelSmall: TextStyle(
|
|
||||||
color: mobileColorTheme.onBackground,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
letterSpacing: 0.05,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
|
||||||
contentPadding: const EdgeInsets.all(8),
|
|
||||||
focusedBorder: const OutlineInputBorder(
|
|
||||||
borderSide: BorderSide(
|
|
||||||
width: 2,
|
|
||||||
color: _primaryColor,
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(6)),
|
|
||||||
),
|
|
||||||
focusedErrorBorder: OutlineInputBorder(
|
|
||||||
borderSide: BorderSide(color: mobileColorTheme.error),
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
|
||||||
),
|
|
||||||
errorBorder: OutlineInputBorder(
|
|
||||||
borderSide: BorderSide(color: mobileColorTheme.error),
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
|
||||||
),
|
|
||||||
enabledBorder: OutlineInputBorder(
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color: mobileColorTheme.outline,
|
|
||||||
),
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
colorScheme: mobileColorTheme,
|
|
||||||
indicatorColor: Colors.blue,
|
|
||||||
extensions: [
|
|
||||||
AFThemeExtension(
|
|
||||||
warning: theme.yellow,
|
|
||||||
success: theme.green,
|
|
||||||
tint1: theme.tint1,
|
|
||||||
tint2: theme.tint2,
|
|
||||||
tint3: theme.tint3,
|
|
||||||
tint4: theme.tint4,
|
|
||||||
tint5: theme.tint5,
|
|
||||||
tint6: theme.tint6,
|
|
||||||
tint7: theme.tint7,
|
|
||||||
tint8: theme.tint8,
|
|
||||||
tint9: theme.tint9,
|
|
||||||
textColor: theme.text,
|
|
||||||
greyHover: theme.hoverBG1,
|
|
||||||
greySelect: theme.bg3,
|
|
||||||
lightGreyHover: theme.hoverBG3,
|
|
||||||
toggleOffFill: theme.shader5,
|
|
||||||
progressBarBGColor: theme.progressBarBGColor,
|
|
||||||
toggleButtonBGColor: theme.toggleButtonBGColor,
|
|
||||||
calendarWeekendBGColor: theme.calendarWeekendBGColor,
|
|
||||||
gridRowCountColor: theme.gridRowCountColor,
|
|
||||||
code: getFontStyle(
|
|
||||||
fontFamily: monospaceFontFamily,
|
|
||||||
fontColor: theme.shader3,
|
|
||||||
),
|
|
||||||
callout: getFontStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: FontSizes.s11,
|
|
||||||
fontColor: theme.shader3,
|
|
||||||
),
|
|
||||||
calloutBGColor: theme.hoverBG3,
|
|
||||||
tableCellBGColor: theme.surface,
|
|
||||||
caption: getFontStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: FontSizes.s11,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
fontColor: theme.hint,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
@ -27,8 +27,8 @@ class MobileHomePageHeader extends StatelessWidget {
|
|||||||
child: BlocBuilder<SettingsUserViewBloc, SettingsUserState>(
|
child: BlocBuilder<SettingsUserViewBloc, SettingsUserState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final userIcon = state.userProfile.iconUrl;
|
final userIcon = state.userProfile.iconUrl;
|
||||||
return SizedBox(
|
return ConstrainedBox(
|
||||||
height: 48,
|
constraints: const BoxConstraints(minHeight: 48),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
FlowyButton(
|
FlowyButton(
|
||||||
@ -61,13 +61,14 @@ class MobileHomePageHeader extends StatelessWidget {
|
|||||||
const HSpace(12),
|
const HSpace(12),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
children: [
|
||||||
const FlowyText.medium(
|
const FlowyText.medium(
|
||||||
'AppFlowy',
|
'AppFlowy',
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
),
|
),
|
||||||
|
const VSpace(4),
|
||||||
FlowyText.regular(
|
FlowyText.regular(
|
||||||
userProfile.email.isNotEmpty
|
userProfile.email.isNotEmpty
|
||||||
? userProfile.email
|
? userProfile.email
|
||||||
|
@ -133,7 +133,7 @@ class _MobileRecentViewState extends State<MobileRecentView> {
|
|||||||
child: FlowyText(
|
child: FlowyText(
|
||||||
view.name,
|
view.name,
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
fontSize: 16.0,
|
fontSize: 14.0,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -9,6 +9,22 @@ import 'package:flowy_infra/theme_extension.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
List<MobileToolbarItem> getMobileToolbarItems() {
|
||||||
|
return [
|
||||||
|
customTextDecorationMobileToolbarItem,
|
||||||
|
buildTextAndBackgroundColorMobileToolbarItem(),
|
||||||
|
mobileAddBlockToolbarItem,
|
||||||
|
mobileConvertBlockToolbarItem,
|
||||||
|
linkMobileToolbarItem,
|
||||||
|
imageMobileToolbarItem,
|
||||||
|
mobileAlignToolbarItem,
|
||||||
|
mobileIndentToolbarItem,
|
||||||
|
mobileOutdentToolbarItem,
|
||||||
|
undoMobileToolbarItem,
|
||||||
|
redoMobileToolbarItem,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, BlockComponentBuilder> getEditorBuilderMap({
|
Map<String, BlockComponentBuilder> getEditorBuilderMap({
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
required EditorState editorState,
|
required EditorState editorState,
|
||||||
|
@ -266,22 +266,16 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
|||||||
_setInitialSelection(editorScrollController);
|
_setInitialSelection(editorScrollController);
|
||||||
|
|
||||||
if (PlatformExtension.isMobile) {
|
if (PlatformExtension.isMobile) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
return MobileToolbarV2(
|
return MobileToolbarV2(
|
||||||
toolbarHeight: 48.0,
|
toolbarHeight: 48.0,
|
||||||
|
backgroundColor: theme.colorScheme.background,
|
||||||
|
foregroundColor: theme.colorScheme.onSurface,
|
||||||
|
iconColor: theme.iconTheme.color ?? theme.colorScheme.onSurface,
|
||||||
|
tabBarSelectedBackgroundColor: theme.colorScheme.background,
|
||||||
|
tabBarSelectedForegroundColor: theme.colorScheme.onSurface,
|
||||||
editorState: editorState,
|
editorState: editorState,
|
||||||
toolbarItems: [
|
toolbarItems: getMobileToolbarItems(),
|
||||||
customTextDecorationMobileToolbarItem,
|
|
||||||
buildTextAndBackgroundColorMobileToolbarItem(),
|
|
||||||
mobileAddBlockToolbarItem,
|
|
||||||
mobileConvertBlockToolbarItem,
|
|
||||||
linkMobileToolbarItem,
|
|
||||||
imageMobileToolbarItem,
|
|
||||||
mobileAlignToolbarItem,
|
|
||||||
mobileIndentToolbarItem,
|
|
||||||
mobileOutdentToolbarItem,
|
|
||||||
undoMobileToolbarItem,
|
|
||||||
redoMobileToolbarItem,
|
|
||||||
],
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
|
@ -581,14 +581,20 @@ class DeleteCoverButton extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final fillColor = PlatformExtension.isDesktopOrWeb
|
||||||
|
? Theme.of(context).colorScheme.surface.withOpacity(0.5)
|
||||||
|
: Theme.of(context).colorScheme.onSurfaceVariant;
|
||||||
|
final svgColor = PlatformExtension.isDesktopOrWeb
|
||||||
|
? Theme.of(context).colorScheme.tertiary
|
||||||
|
: Theme.of(context).colorScheme.onPrimary;
|
||||||
return FlowyIconButton(
|
return FlowyIconButton(
|
||||||
hoverColor: Theme.of(context).colorScheme.surface,
|
hoverColor: Theme.of(context).colorScheme.surface,
|
||||||
fillColor: Theme.of(context).colorScheme.surface.withOpacity(0.5),
|
fillColor: fillColor,
|
||||||
iconPadding: const EdgeInsets.all(5),
|
iconPadding: const EdgeInsets.all(5),
|
||||||
width: 28,
|
width: 28,
|
||||||
icon: FlowySvg(
|
icon: FlowySvg(
|
||||||
FlowySvgs.delete_s,
|
FlowySvgs.delete_s,
|
||||||
color: Theme.of(context).colorScheme.tertiary,
|
color: svgColor,
|
||||||
),
|
),
|
||||||
onPressed: onTap,
|
onPressed: onTap,
|
||||||
);
|
);
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
final customTextDecorationMobileToolbarItem = MobileToolbarItem.withMenu(
|
final customTextDecorationMobileToolbarItem = MobileToolbarItem.withMenu(
|
||||||
itemIconBuilder: (_, __, ___) => const AFMobileIcon(
|
itemIconBuilder: (_, __, ___) => const FlowySvg(
|
||||||
afMobileIcons: AFMobileIcons.textDecoration,
|
FlowySvgs.text_s,
|
||||||
|
size: Size.square(24),
|
||||||
),
|
),
|
||||||
itemMenuBuilder: (_, editorState, __) {
|
itemMenuBuilder: (_, editorState, __) {
|
||||||
final selection = editorState.selection;
|
final selection = editorState.selection;
|
||||||
@ -82,6 +84,7 @@ class _TextDecorationMenuState extends State<_TextDecorationMenu> {
|
|||||||
return MobileToolbarItemMenuBtn(
|
return MobileToolbarItemMenuBtn(
|
||||||
icon: AFMobileIcon(
|
icon: AFMobileIcon(
|
||||||
afMobileIcons: currentDecoration.icon,
|
afMobileIcons: currentDecoration.icon,
|
||||||
|
color: MobileToolbarTheme.of(context).iconColor,
|
||||||
),
|
),
|
||||||
label: FlowyText(currentDecoration.label),
|
label: FlowyText(currentDecoration.label),
|
||||||
isSelected: isSelected,
|
isSelected: isSelected,
|
||||||
|
@ -17,9 +17,13 @@ import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
|
|||||||
import 'package:appflowy/user/application/user_listener.dart';
|
import 'package:appflowy/user/application/user_listener.dart';
|
||||||
import 'package:appflowy/user/application/user_service.dart';
|
import 'package:appflowy/user/application/user_service.dart';
|
||||||
import 'package:appflowy/user/presentation/router.dart';
|
import 'package:appflowy/user/presentation/router.dart';
|
||||||
|
import 'package:appflowy/util/platform_extension.dart';
|
||||||
import 'package:appflowy/workspace/application/edit_panel/edit_panel_bloc.dart';
|
import 'package:appflowy/workspace/application/edit_panel/edit_panel_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
|
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/notifications/notification_action_bloc.dart';
|
import 'package:appflowy/workspace/application/notifications/notification_action_bloc.dart';
|
||||||
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
|
import 'package:appflowy/workspace/application/settings/appearance/desktop_appearance.dart';
|
||||||
|
import 'package:appflowy/workspace/application/settings/appearance/mobile_appearance.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
||||||
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/user/prelude.dart';
|
import 'package:appflowy/workspace/application/user/prelude.dart';
|
||||||
@ -102,6 +106,11 @@ void _resolveCommonService(
|
|||||||
getIt.registerFactory<ClipboardService>(
|
getIt.registerFactory<ClipboardService>(
|
||||||
() => ClipboardService(),
|
() => ClipboardService(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// theme
|
||||||
|
getIt.registerFactory<BaseAppearance>(
|
||||||
|
() => PlatformExtension.isMobile ? MobileAppearance() : DesktopAppearance(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _resolveUserDeps(GetIt getIt, IntegrationMode mode) {
|
void _resolveUserDeps(GetIt getIt, IntegrationMode mode) {
|
||||||
|
@ -1,25 +1,20 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:appflowy/mobile/application/mobile_theme_data.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/user/application/user_settings_service.dart';
|
import 'package:appflowy/user/application/user_settings_service.dart';
|
||||||
import 'package:appflowy/util/platform_extension.dart';
|
|
||||||
import 'package:appflowy/workspace/application/appearance_defaults.dart';
|
import 'package:appflowy/workspace/application/appearance_defaults.dart';
|
||||||
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
import 'package:appflowy_backend/log.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/date_time.pbenum.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/date_time.pbenum.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/size.dart';
|
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
|
||||||
|
|
||||||
part 'appearance_cubit.freezed.dart';
|
part 'appearance_cubit.freezed.dart';
|
||||||
|
|
||||||
const _white = Color(0xFFFFFFFF);
|
|
||||||
|
|
||||||
/// [AppearanceSettingsCubit] is used to modify the appearance of AppFlowy.
|
/// [AppearanceSettingsCubit] is used to modify the appearance of AppFlowy.
|
||||||
/// It includes:
|
/// It includes:
|
||||||
/// - [AppTheme]
|
/// - [AppTheme]
|
||||||
@ -349,251 +344,11 @@ class AppearanceSettingsState with _$AppearanceSettingsState {
|
|||||||
ThemeData get darkTheme => _getThemeData(Brightness.dark);
|
ThemeData get darkTheme => _getThemeData(Brightness.dark);
|
||||||
|
|
||||||
ThemeData _getThemeData(Brightness brightness) {
|
ThemeData _getThemeData(Brightness brightness) {
|
||||||
// Poppins and SF Mono are not well supported in some languages, so use the
|
return getIt<BaseAppearance>().getThemeData(
|
||||||
// built-in font for the following languages.
|
appTheme,
|
||||||
final useBuiltInFontLanguages = [
|
brightness,
|
||||||
const Locale('zh', 'CN'),
|
font,
|
||||||
const Locale('zh', 'TW'),
|
monospaceFont,
|
||||||
];
|
|
||||||
String fontFamily = font;
|
|
||||||
String monospaceFontFamily = monospaceFont;
|
|
||||||
if (useBuiltInFontLanguages.contains(locale)) {
|
|
||||||
fontFamily = '';
|
|
||||||
monospaceFontFamily = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
final theme = brightness == Brightness.light
|
|
||||||
? appTheme.lightTheme
|
|
||||||
: appTheme.darkTheme;
|
|
||||||
|
|
||||||
final colorScheme = ColorScheme(
|
|
||||||
brightness: brightness,
|
|
||||||
primary: theme.primary,
|
|
||||||
onPrimary: theme.onPrimary,
|
|
||||||
primaryContainer: theme.main2,
|
|
||||||
onPrimaryContainer: _white,
|
|
||||||
// page title hover color
|
|
||||||
secondary: theme.hoverBG1,
|
|
||||||
onSecondary: theme.shader1,
|
|
||||||
// setting value hover color
|
|
||||||
secondaryContainer: theme.selector,
|
|
||||||
onSecondaryContainer: theme.topbarBg,
|
|
||||||
tertiary: theme.shader7,
|
|
||||||
// Editor: toolbarColor
|
|
||||||
onTertiary: theme.toolbarColor,
|
|
||||||
tertiaryContainer: theme.questionBubbleBG,
|
|
||||||
background: theme.surface,
|
|
||||||
onBackground: theme.text,
|
|
||||||
surface: theme.surface,
|
|
||||||
// text&icon color when it is hovered
|
|
||||||
onSurface: theme.hoverFG,
|
|
||||||
// grey hover color
|
|
||||||
inverseSurface: theme.hoverBG3,
|
|
||||||
onError: theme.onPrimary,
|
|
||||||
error: theme.red,
|
|
||||||
outline: theme.shader4,
|
|
||||||
surfaceVariant: theme.sidebarBg,
|
|
||||||
shadow: theme.shadow,
|
|
||||||
);
|
|
||||||
|
|
||||||
const Set<MaterialState> scrollbarInteractiveStates = <MaterialState>{
|
|
||||||
MaterialState.pressed,
|
|
||||||
MaterialState.hovered,
|
|
||||||
MaterialState.dragged,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (PlatformExtension.isMobile) {
|
|
||||||
// Mobile version has only one theme(light mode) for now.
|
|
||||||
// The desktop theme and the mobile theme are independent.
|
|
||||||
final mobileThemeData = getMobileThemeData(
|
|
||||||
brightness,
|
|
||||||
theme,
|
|
||||||
fontFamily,
|
|
||||||
monospaceFontFamily,
|
|
||||||
);
|
|
||||||
return mobileThemeData;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Due to Desktop version has multiple themes, it relies on the current theme to build the ThemeData
|
|
||||||
final desktopThemeData = ThemeData(
|
|
||||||
brightness: brightness,
|
|
||||||
dialogBackgroundColor: theme.surface,
|
|
||||||
textTheme: getTextTheme(fontFamily: fontFamily, fontColor: theme.text),
|
|
||||||
textSelectionTheme: TextSelectionThemeData(
|
|
||||||
cursorColor: theme.main2,
|
|
||||||
selectionHandleColor: theme.main2,
|
|
||||||
),
|
|
||||||
iconTheme: IconThemeData(color: theme.icon),
|
|
||||||
tooltipTheme: TooltipThemeData(
|
|
||||||
textStyle: getFontStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: FontSizes.s11,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
fontColor: theme.surface,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
scaffoldBackgroundColor: theme.surface,
|
|
||||||
snackBarTheme: SnackBarThemeData(
|
|
||||||
backgroundColor: colorScheme.primary,
|
|
||||||
contentTextStyle: TextStyle(color: colorScheme.onSurface),
|
|
||||||
),
|
|
||||||
scrollbarTheme: ScrollbarThemeData(
|
|
||||||
thumbColor: MaterialStateProperty.resolveWith((states) {
|
|
||||||
if (states.any(scrollbarInteractiveStates.contains)) {
|
|
||||||
return theme.shader7;
|
|
||||||
}
|
|
||||||
return theme.shader5;
|
|
||||||
}),
|
|
||||||
thickness: MaterialStateProperty.resolveWith((states) {
|
|
||||||
if (states.any(scrollbarInteractiveStates.contains)) {
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
return 3.0;
|
|
||||||
}),
|
|
||||||
crossAxisMargin: 0.0,
|
|
||||||
mainAxisMargin: 6.0,
|
|
||||||
radius: Corners.s10Radius,
|
|
||||||
),
|
|
||||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
||||||
//dropdown menu color
|
|
||||||
canvasColor: theme.surface,
|
|
||||||
dividerColor: theme.divider,
|
|
||||||
hintColor: theme.hint,
|
|
||||||
//action item hover color
|
|
||||||
hoverColor: theme.hoverBG2,
|
|
||||||
disabledColor: theme.shader4,
|
|
||||||
highlightColor: theme.main1,
|
|
||||||
indicatorColor: theme.main1,
|
|
||||||
cardColor: theme.input,
|
|
||||||
colorScheme: colorScheme,
|
|
||||||
extensions: [
|
|
||||||
AFThemeExtension(
|
|
||||||
warning: theme.yellow,
|
|
||||||
success: theme.green,
|
|
||||||
tint1: theme.tint1,
|
|
||||||
tint2: theme.tint2,
|
|
||||||
tint3: theme.tint3,
|
|
||||||
tint4: theme.tint4,
|
|
||||||
tint5: theme.tint5,
|
|
||||||
tint6: theme.tint6,
|
|
||||||
tint7: theme.tint7,
|
|
||||||
tint8: theme.tint8,
|
|
||||||
tint9: theme.tint9,
|
|
||||||
textColor: theme.text,
|
|
||||||
greyHover: theme.hoverBG1,
|
|
||||||
greySelect: theme.bg3,
|
|
||||||
lightGreyHover: theme.hoverBG3,
|
|
||||||
toggleOffFill: theme.shader5,
|
|
||||||
progressBarBGColor: theme.progressBarBGColor,
|
|
||||||
toggleButtonBGColor: theme.toggleButtonBGColor,
|
|
||||||
calendarWeekendBGColor: theme.calendarWeekendBGColor,
|
|
||||||
gridRowCountColor: theme.gridRowCountColor,
|
|
||||||
code: getFontStyle(
|
|
||||||
fontFamily: monospaceFontFamily,
|
|
||||||
fontColor: theme.shader3,
|
|
||||||
),
|
|
||||||
callout: getFontStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: FontSizes.s11,
|
|
||||||
fontColor: theme.shader3,
|
|
||||||
),
|
|
||||||
calloutBGColor: theme.hoverBG3,
|
|
||||||
tableCellBGColor: theme.surface,
|
|
||||||
caption: getFontStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: FontSizes.s11,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
fontColor: theme.hint,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
return desktopThemeData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TextStyle getFontStyle({
|
|
||||||
required String fontFamily,
|
|
||||||
double? fontSize,
|
|
||||||
FontWeight? fontWeight,
|
|
||||||
Color? fontColor,
|
|
||||||
double? letterSpacing,
|
|
||||||
double? lineHeight,
|
|
||||||
}) {
|
|
||||||
try {
|
|
||||||
return GoogleFonts.getFont(
|
|
||||||
fontFamily,
|
|
||||||
fontSize: fontSize ?? FontSizes.s12,
|
|
||||||
color: fontColor,
|
|
||||||
fontWeight: fontWeight ?? FontWeight.w500,
|
|
||||||
letterSpacing: (fontSize ?? FontSizes.s12) * (letterSpacing ?? 0.005),
|
|
||||||
height: lineHeight,
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
return TextStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: fontSize ?? FontSizes.s12,
|
|
||||||
color: fontColor,
|
|
||||||
fontWeight: fontWeight ?? FontWeight.w500,
|
|
||||||
fontFamilyFallback: const ["Noto Color Emoji"],
|
|
||||||
letterSpacing: (fontSize ?? FontSizes.s12) * (letterSpacing ?? 0.005),
|
|
||||||
height: lineHeight,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextTheme getTextTheme({
|
|
||||||
required String fontFamily,
|
|
||||||
required Color fontColor,
|
|
||||||
}) {
|
|
||||||
return TextTheme(
|
|
||||||
displayLarge: getFontStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: FontSizes.s32,
|
|
||||||
fontColor: fontColor,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
lineHeight: 42.0,
|
|
||||||
), // h2
|
|
||||||
displayMedium: getFontStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: FontSizes.s24,
|
|
||||||
fontColor: fontColor,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
lineHeight: 34.0,
|
|
||||||
), // h3
|
|
||||||
displaySmall: getFontStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: FontSizes.s20,
|
|
||||||
fontColor: fontColor,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
lineHeight: 28.0,
|
|
||||||
), // h4
|
|
||||||
titleLarge: getFontStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: FontSizes.s18,
|
|
||||||
fontColor: fontColor,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
), // title
|
|
||||||
titleMedium: getFontStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: FontSizes.s16,
|
|
||||||
fontColor: fontColor,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
), // heading
|
|
||||||
titleSmall: getFontStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontSize: FontSizes.s14,
|
|
||||||
fontColor: fontColor,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
), // subheading
|
|
||||||
bodyMedium: getFontStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontColor: fontColor,
|
|
||||||
), // body-regular
|
|
||||||
bodySmall: getFontStyle(
|
|
||||||
fontFamily: fontFamily,
|
|
||||||
fontColor: fontColor,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
), // body-thin
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,107 @@
|
|||||||
|
import 'package:flowy_infra/size.dart';
|
||||||
|
import 'package:flowy_infra/theme.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
abstract class BaseAppearance {
|
||||||
|
final white = const Color(0xFFFFFFFF);
|
||||||
|
|
||||||
|
final Set<MaterialState> scrollbarInteractiveStates = <MaterialState>{
|
||||||
|
MaterialState.pressed,
|
||||||
|
MaterialState.hovered,
|
||||||
|
MaterialState.dragged,
|
||||||
|
};
|
||||||
|
|
||||||
|
TextStyle getFontStyle({
|
||||||
|
required String fontFamily,
|
||||||
|
double? fontSize,
|
||||||
|
FontWeight? fontWeight,
|
||||||
|
Color? fontColor,
|
||||||
|
double? letterSpacing,
|
||||||
|
double? lineHeight,
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
return GoogleFonts.getFont(
|
||||||
|
fontFamily,
|
||||||
|
fontSize: fontSize ?? FontSizes.s12,
|
||||||
|
color: fontColor,
|
||||||
|
fontWeight: fontWeight ?? FontWeight.w500,
|
||||||
|
letterSpacing: (fontSize ?? FontSizes.s12) * (letterSpacing ?? 0.005),
|
||||||
|
height: lineHeight,
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
return TextStyle(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontSize: fontSize ?? FontSizes.s12,
|
||||||
|
color: fontColor,
|
||||||
|
fontWeight: fontWeight ?? FontWeight.w500,
|
||||||
|
fontFamilyFallback: const ['Poppins'],
|
||||||
|
letterSpacing: (fontSize ?? FontSizes.s12) * (letterSpacing ?? 0.005),
|
||||||
|
height: lineHeight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextTheme getTextTheme({
|
||||||
|
required String fontFamily,
|
||||||
|
required Color fontColor,
|
||||||
|
}) {
|
||||||
|
return TextTheme(
|
||||||
|
displayLarge: getFontStyle(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontSize: FontSizes.s32,
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
lineHeight: 42.0,
|
||||||
|
), // h2
|
||||||
|
displayMedium: getFontStyle(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontSize: FontSizes.s24,
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
lineHeight: 34.0,
|
||||||
|
), // h3
|
||||||
|
displaySmall: getFontStyle(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontSize: FontSizes.s20,
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
lineHeight: 28.0,
|
||||||
|
), // h4
|
||||||
|
titleLarge: getFontStyle(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontSize: FontSizes.s18,
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
), // title
|
||||||
|
titleMedium: getFontStyle(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontSize: FontSizes.s16,
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
), // heading
|
||||||
|
titleSmall: getFontStyle(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontSize: FontSizes.s14,
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
), // subheading
|
||||||
|
bodyMedium: getFontStyle(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontColor: fontColor,
|
||||||
|
), // body-regular
|
||||||
|
bodySmall: getFontStyle(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontColor: fontColor,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
), // body-thin
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThemeData getThemeData(
|
||||||
|
AppTheme appTheme,
|
||||||
|
Brightness brightness,
|
||||||
|
String fontFamily,
|
||||||
|
String codeFontFamily,
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,150 @@
|
|||||||
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
|
import 'package:flowy_infra/size.dart';
|
||||||
|
import 'package:flowy_infra/theme.dart';
|
||||||
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class DesktopAppearance extends BaseAppearance {
|
||||||
|
@override
|
||||||
|
ThemeData getThemeData(
|
||||||
|
AppTheme appTheme,
|
||||||
|
Brightness brightness,
|
||||||
|
String fontFamily,
|
||||||
|
String codeFontFamily,
|
||||||
|
) {
|
||||||
|
assert(fontFamily.isNotEmpty);
|
||||||
|
assert(codeFontFamily.isNotEmpty);
|
||||||
|
|
||||||
|
final theme = brightness == Brightness.light
|
||||||
|
? appTheme.lightTheme
|
||||||
|
: appTheme.darkTheme;
|
||||||
|
|
||||||
|
final colorScheme = ColorScheme(
|
||||||
|
brightness: brightness,
|
||||||
|
primary: theme.primary,
|
||||||
|
onPrimary: theme.onPrimary,
|
||||||
|
primaryContainer: theme.main2,
|
||||||
|
onPrimaryContainer: white,
|
||||||
|
// page title hover color
|
||||||
|
secondary: theme.hoverBG1,
|
||||||
|
onSecondary: theme.shader1,
|
||||||
|
// setting value hover color
|
||||||
|
secondaryContainer: theme.selector,
|
||||||
|
onSecondaryContainer: theme.topbarBg,
|
||||||
|
tertiary: theme.shader7,
|
||||||
|
// Editor: toolbarColor
|
||||||
|
onTertiary: theme.toolbarColor,
|
||||||
|
tertiaryContainer: theme.questionBubbleBG,
|
||||||
|
background: theme.surface,
|
||||||
|
onBackground: theme.text,
|
||||||
|
surface: theme.surface,
|
||||||
|
// text&icon color when it is hovered
|
||||||
|
onSurface: theme.hoverFG,
|
||||||
|
// grey hover color
|
||||||
|
inverseSurface: theme.hoverBG3,
|
||||||
|
onError: theme.onPrimary,
|
||||||
|
error: theme.red,
|
||||||
|
outline: theme.shader4,
|
||||||
|
surfaceVariant: theme.sidebarBg,
|
||||||
|
shadow: theme.shadow,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Due to Desktop version has multiple themes, it relies on the current theme to build the ThemeData
|
||||||
|
return ThemeData(
|
||||||
|
brightness: brightness,
|
||||||
|
dialogBackgroundColor: theme.surface,
|
||||||
|
textTheme: getTextTheme(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontColor: theme.text,
|
||||||
|
),
|
||||||
|
textSelectionTheme: TextSelectionThemeData(
|
||||||
|
cursorColor: theme.main2,
|
||||||
|
selectionHandleColor: theme.main2,
|
||||||
|
),
|
||||||
|
iconTheme: IconThemeData(color: theme.icon),
|
||||||
|
tooltipTheme: TooltipThemeData(
|
||||||
|
textStyle: getFontStyle(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontSize: FontSizes.s11,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontColor: theme.surface,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
scaffoldBackgroundColor: theme.surface,
|
||||||
|
snackBarTheme: SnackBarThemeData(
|
||||||
|
backgroundColor: colorScheme.primary,
|
||||||
|
contentTextStyle: TextStyle(color: colorScheme.onSurface),
|
||||||
|
),
|
||||||
|
scrollbarTheme: ScrollbarThemeData(
|
||||||
|
thumbColor: MaterialStateProperty.resolveWith((states) {
|
||||||
|
if (states.any(scrollbarInteractiveStates.contains)) {
|
||||||
|
return theme.shader7;
|
||||||
|
}
|
||||||
|
return theme.shader5;
|
||||||
|
}),
|
||||||
|
thickness: MaterialStateProperty.resolveWith((states) {
|
||||||
|
if (states.any(scrollbarInteractiveStates.contains)) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
return 3.0;
|
||||||
|
}),
|
||||||
|
crossAxisMargin: 0.0,
|
||||||
|
mainAxisMargin: 6.0,
|
||||||
|
radius: Corners.s10Radius,
|
||||||
|
),
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
//dropdown menu color
|
||||||
|
canvasColor: theme.surface,
|
||||||
|
dividerColor: theme.divider,
|
||||||
|
hintColor: theme.hint,
|
||||||
|
//action item hover color
|
||||||
|
hoverColor: theme.hoverBG2,
|
||||||
|
disabledColor: theme.shader4,
|
||||||
|
highlightColor: theme.main1,
|
||||||
|
indicatorColor: theme.main1,
|
||||||
|
cardColor: theme.input,
|
||||||
|
colorScheme: colorScheme,
|
||||||
|
extensions: [
|
||||||
|
AFThemeExtension(
|
||||||
|
warning: theme.yellow,
|
||||||
|
success: theme.green,
|
||||||
|
tint1: theme.tint1,
|
||||||
|
tint2: theme.tint2,
|
||||||
|
tint3: theme.tint3,
|
||||||
|
tint4: theme.tint4,
|
||||||
|
tint5: theme.tint5,
|
||||||
|
tint6: theme.tint6,
|
||||||
|
tint7: theme.tint7,
|
||||||
|
tint8: theme.tint8,
|
||||||
|
tint9: theme.tint9,
|
||||||
|
textColor: theme.text,
|
||||||
|
greyHover: theme.hoverBG1,
|
||||||
|
greySelect: theme.bg3,
|
||||||
|
lightGreyHover: theme.hoverBG3,
|
||||||
|
toggleOffFill: theme.shader5,
|
||||||
|
progressBarBGColor: theme.progressBarBGColor,
|
||||||
|
toggleButtonBGColor: theme.toggleButtonBGColor,
|
||||||
|
calendarWeekendBGColor: theme.calendarWeekendBGColor,
|
||||||
|
gridRowCountColor: theme.gridRowCountColor,
|
||||||
|
code: getFontStyle(
|
||||||
|
fontFamily: codeFontFamily,
|
||||||
|
fontColor: theme.shader3,
|
||||||
|
),
|
||||||
|
callout: getFontStyle(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontSize: FontSizes.s11,
|
||||||
|
fontColor: theme.shader3,
|
||||||
|
),
|
||||||
|
calloutBGColor: theme.hoverBG3,
|
||||||
|
tableCellBGColor: theme.surface,
|
||||||
|
caption: getFontStyle(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
fontSize: FontSizes.s11,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontColor: theme.hint,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,282 @@
|
|||||||
|
// ThemeData in mobile
|
||||||
|
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
|
||||||
|
import 'package:flowy_infra/size.dart';
|
||||||
|
import 'package:flowy_infra/theme.dart';
|
||||||
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class MobileAppearance extends BaseAppearance {
|
||||||
|
static const _primaryColor = Color(0xFF2DA2F6); //primary 100
|
||||||
|
static const _onBackgroundColor = Color(0xff2F3030); // text/title color
|
||||||
|
static const _onSurfaceColor = Color(0xff676666); // text/body color
|
||||||
|
static const _onSecondaryColor = Color(0xFFC5C7CB); // text/body2 color
|
||||||
|
|
||||||
|
@override
|
||||||
|
ThemeData getThemeData(
|
||||||
|
AppTheme appTheme,
|
||||||
|
Brightness brightness,
|
||||||
|
String fontFamily,
|
||||||
|
String codeFontFamily,
|
||||||
|
) {
|
||||||
|
assert(fontFamily.isNotEmpty);
|
||||||
|
assert(codeFontFamily.isNotEmpty);
|
||||||
|
|
||||||
|
final fontStyle = getFontStyle(
|
||||||
|
fontFamily: fontFamily,
|
||||||
|
);
|
||||||
|
final codeFontStyle = getFontStyle(
|
||||||
|
fontFamily: codeFontFamily,
|
||||||
|
);
|
||||||
|
|
||||||
|
final theme = brightness == Brightness.light
|
||||||
|
? appTheme.lightTheme
|
||||||
|
: appTheme.darkTheme;
|
||||||
|
|
||||||
|
final colorTheme = brightness == Brightness.light
|
||||||
|
? ColorScheme(
|
||||||
|
brightness: brightness,
|
||||||
|
primary: _primaryColor,
|
||||||
|
onPrimary: Colors.white,
|
||||||
|
// TODO(yijing): add color later
|
||||||
|
secondary: Colors.white,
|
||||||
|
onSecondary: _onSecondaryColor,
|
||||||
|
error: const Color(0xffFB006D),
|
||||||
|
onError: const Color(0xffFB006D),
|
||||||
|
background: Colors.white,
|
||||||
|
onBackground: _onBackgroundColor,
|
||||||
|
outline: const Color(0xffE3E3E3), //caption
|
||||||
|
// outline: const Color(0xffBDC0C5), //caption
|
||||||
|
outlineVariant: const Color(0xffCBD5E0).withOpacity(0.24),
|
||||||
|
//Snack bar
|
||||||
|
surface: Colors.white,
|
||||||
|
onSurface: _onSurfaceColor, // text/body color
|
||||||
|
surfaceVariant: const Color.fromARGB(255, 216, 216, 216),
|
||||||
|
)
|
||||||
|
: ColorScheme(
|
||||||
|
brightness: brightness,
|
||||||
|
primary: _primaryColor,
|
||||||
|
onPrimary: Colors.white,
|
||||||
|
// TODO(yijing): add color later
|
||||||
|
secondary: Colors.black,
|
||||||
|
onSecondary: Colors.white,
|
||||||
|
error: const Color(0xffFB006D),
|
||||||
|
onError: const Color(0xffFB006D),
|
||||||
|
background: const Color(0xff1C1C1E), // BG/Secondary color
|
||||||
|
onBackground: Colors.white,
|
||||||
|
outline: const Color(0xff96989C), //caption
|
||||||
|
outlineVariant: Colors.black,
|
||||||
|
//Snack bar
|
||||||
|
surface: const Color(0xff2F3030),
|
||||||
|
onSurface: const Color(0xffC5C6C7), // text/body color
|
||||||
|
);
|
||||||
|
|
||||||
|
return ThemeData(
|
||||||
|
// color
|
||||||
|
primaryColor: colorTheme.primary, //primary 100
|
||||||
|
primaryColorLight: const Color(0xFF57B5F8), //primary 80
|
||||||
|
dividerColor: colorTheme.outline, //caption
|
||||||
|
hintColor: colorTheme.outline,
|
||||||
|
disabledColor: colorTheme.outline,
|
||||||
|
scaffoldBackgroundColor: colorTheme.background,
|
||||||
|
appBarTheme: AppBarTheme(
|
||||||
|
foregroundColor: colorTheme.onBackground,
|
||||||
|
backgroundColor: colorTheme.background,
|
||||||
|
centerTitle: false,
|
||||||
|
titleTextStyle: TextStyle(
|
||||||
|
color: colorTheme.onBackground,
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
letterSpacing: 0.05,
|
||||||
|
),
|
||||||
|
shadowColor: colorTheme.outlineVariant,
|
||||||
|
),
|
||||||
|
radioTheme: RadioThemeData(
|
||||||
|
fillColor: MaterialStateProperty.resolveWith((states) {
|
||||||
|
if (states.contains(MaterialState.selected)) {
|
||||||
|
return colorTheme.primary;
|
||||||
|
}
|
||||||
|
return colorTheme.outline;
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
// button
|
||||||
|
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||||
|
style: ButtonStyle(
|
||||||
|
fixedSize: MaterialStateProperty.all(const Size.fromHeight(48)),
|
||||||
|
elevation: MaterialStateProperty.all(0),
|
||||||
|
textStyle: MaterialStateProperty.all(
|
||||||
|
const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
shadowColor: MaterialStateProperty.all(null),
|
||||||
|
backgroundColor: MaterialStateProperty.resolveWith<Color>(
|
||||||
|
(Set<MaterialState> states) {
|
||||||
|
if (states.contains(MaterialState.disabled)) {
|
||||||
|
return const Color(0xFF57B5F8);
|
||||||
|
}
|
||||||
|
return colorTheme.primary;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
foregroundColor: MaterialStateProperty.all(Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
outlinedButtonTheme: OutlinedButtonThemeData(
|
||||||
|
style: ButtonStyle(
|
||||||
|
textStyle: MaterialStateProperty.all(
|
||||||
|
const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
foregroundColor: MaterialStateProperty.all(
|
||||||
|
colorTheme.onBackground,
|
||||||
|
),
|
||||||
|
backgroundColor: MaterialStateProperty.all(colorTheme.background),
|
||||||
|
shape: MaterialStateProperty.all(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
side: MaterialStateProperty.all(
|
||||||
|
BorderSide(
|
||||||
|
color: colorTheme.outline,
|
||||||
|
width: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
padding: MaterialStateProperty.all(
|
||||||
|
const EdgeInsets.symmetric(horizontal: 8, vertical: 12),
|
||||||
|
),
|
||||||
|
// splash color
|
||||||
|
overlayColor: MaterialStateProperty.all(
|
||||||
|
Colors.grey[100],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
textButtonTheme: TextButtonThemeData(
|
||||||
|
style: ButtonStyle(
|
||||||
|
textStyle: MaterialStateProperty.all(
|
||||||
|
fontStyle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// text
|
||||||
|
fontFamily: fontStyle.fontFamily,
|
||||||
|
textTheme: TextTheme(
|
||||||
|
displayLarge: const TextStyle(
|
||||||
|
color: Color(0xFF57B5F8),
|
||||||
|
fontSize: 32,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
height: 1.20,
|
||||||
|
letterSpacing: 0.16,
|
||||||
|
),
|
||||||
|
displayMedium: fontStyle.copyWith(
|
||||||
|
color: colorTheme.onBackground,
|
||||||
|
fontSize: 32,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
height: 1.20,
|
||||||
|
letterSpacing: 0.16,
|
||||||
|
),
|
||||||
|
// H1 Semi 26
|
||||||
|
displaySmall: fontStyle.copyWith(
|
||||||
|
color: colorTheme.onBackground,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
height: 1.10,
|
||||||
|
letterSpacing: 0.13,
|
||||||
|
),
|
||||||
|
// body2 14 Regular
|
||||||
|
bodyMedium: fontStyle.copyWith(
|
||||||
|
color: colorTheme.onBackground,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
// height: 1.2,
|
||||||
|
letterSpacing: 0.07,
|
||||||
|
),
|
||||||
|
// Trash empty title
|
||||||
|
labelLarge: fontStyle.copyWith(
|
||||||
|
color: colorTheme.onBackground,
|
||||||
|
fontSize: 22,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
letterSpacing: -0.3,
|
||||||
|
),
|
||||||
|
// setting item title
|
||||||
|
labelMedium: fontStyle.copyWith(
|
||||||
|
color: colorTheme.onSurface,
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
// setting group title
|
||||||
|
labelSmall: fontStyle.copyWith(
|
||||||
|
color: colorTheme.onBackground,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
letterSpacing: 0.05,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
|
contentPadding: const EdgeInsets.all(8),
|
||||||
|
focusedBorder: const OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
width: 2,
|
||||||
|
color: _primaryColor,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(6)),
|
||||||
|
),
|
||||||
|
focusedErrorBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: colorTheme.error),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||||
|
),
|
||||||
|
errorBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: colorTheme.error),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: colorTheme.outline,
|
||||||
|
),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
colorScheme: colorTheme,
|
||||||
|
indicatorColor: Colors.blue,
|
||||||
|
extensions: [
|
||||||
|
AFThemeExtension(
|
||||||
|
warning: theme.yellow,
|
||||||
|
success: theme.green,
|
||||||
|
tint1: theme.tint1,
|
||||||
|
tint2: theme.tint2,
|
||||||
|
tint3: theme.tint3,
|
||||||
|
tint4: theme.tint4,
|
||||||
|
tint5: theme.tint5,
|
||||||
|
tint6: theme.tint6,
|
||||||
|
tint7: theme.tint7,
|
||||||
|
tint8: theme.tint8,
|
||||||
|
tint9: theme.tint9,
|
||||||
|
textColor: theme.text,
|
||||||
|
greyHover: theme.hoverBG1,
|
||||||
|
greySelect: theme.bg3,
|
||||||
|
lightGreyHover: theme.hoverBG3,
|
||||||
|
toggleOffFill: theme.shader5,
|
||||||
|
progressBarBGColor: theme.progressBarBGColor,
|
||||||
|
toggleButtonBGColor: theme.toggleButtonBGColor,
|
||||||
|
calendarWeekendBGColor: theme.calendarWeekendBGColor,
|
||||||
|
gridRowCountColor: theme.gridRowCountColor,
|
||||||
|
code: codeFontStyle.copyWith(
|
||||||
|
color: theme.shader3,
|
||||||
|
),
|
||||||
|
callout: fontStyle.copyWith(
|
||||||
|
fontSize: FontSizes.s11,
|
||||||
|
color: theme.shader3,
|
||||||
|
),
|
||||||
|
calloutBGColor: theme.hoverBG3,
|
||||||
|
tableCellBGColor: theme.surface,
|
||||||
|
caption: fontStyle.copyWith(
|
||||||
|
fontSize: FontSizes.s11,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: theme.hint,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -54,8 +54,8 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: "2617f7"
|
ref: ec3ecf5
|
||||||
resolved-ref: "2617f766a5a4aa83c9f4d5c4d7221c12dbe23b66"
|
resolved-ref: ec3ecf58a0de453561d30e809c6dc1eed3d1aa9a
|
||||||
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
||||||
source: git
|
source: git
|
||||||
version: "2.0.0-beta.1"
|
version: "2.0.0-beta.1"
|
||||||
|
@ -47,7 +47,7 @@ dependencies:
|
|||||||
appflowy_editor:
|
appflowy_editor:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
||||||
ref: '2617f7'
|
ref: 'ec3ecf5'
|
||||||
|
|
||||||
appflowy_popover:
|
appflowy_popover:
|
||||||
path: packages/appflowy_popover
|
path: packages/appflowy_popover
|
||||||
|
Reference in New Issue
Block a user