mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: mobile bugs fix (#4059)
* fix: add missing tap gesture * fix: unify bottom sheet shape and padding * fix: fail to pop the detail page when add new card * fix: show card title placeholder when it is empty * refactor: ThirdPartySignInButtons * chore: add resizeToAvoidBottomInset in showFlowyMobileBottomSheet * chore: refactor code
This commit is contained in:
parent
5ff6405f7f
commit
9824d5980a
@ -17,10 +17,10 @@ class MobileTextCardCell<CustomCardData> extends CardCell {
|
||||
final CellControllerBuilder cellControllerBuilder;
|
||||
|
||||
@override
|
||||
State<MobileTextCardCell> createState() => _NumberCellState();
|
||||
State<MobileTextCardCell> createState() => _MobileTextCardCellState();
|
||||
}
|
||||
|
||||
class _NumberCellState extends State<MobileTextCardCell> {
|
||||
class _MobileTextCardCellState extends State<MobileTextCardCell> {
|
||||
late final TextCellBloc _cellBloc;
|
||||
|
||||
@override
|
||||
@ -47,9 +47,8 @@ class _NumberCellState extends State<MobileTextCardCell> {
|
||||
child: BlocBuilder<TextCellBloc, TextCellState>(
|
||||
buildWhen: (previous, current) => previous.content != current.content,
|
||||
builder: (context, state) {
|
||||
if (state.content.isEmpty) {
|
||||
return const SizedBox();
|
||||
} else {
|
||||
// return custom widget if render hook is provided(for example, the title of the card on board view)
|
||||
// if widget.cardData.isEmpty means there is no data for this cell
|
||||
final Widget? custom = widget.renderHook?.call(
|
||||
state.content,
|
||||
widget.cardData,
|
||||
@ -59,6 +58,12 @@ class _NumberCellState extends State<MobileTextCardCell> {
|
||||
return custom;
|
||||
}
|
||||
|
||||
// if there is no render hook
|
||||
// the empty text cell will be hidden
|
||||
if (state.content.isEmpty) {
|
||||
return const SizedBox();
|
||||
}
|
||||
|
||||
return Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
padding: cellStyle.padding,
|
||||
@ -67,7 +72,6 @@ class _NumberCellState extends State<MobileTextCardCell> {
|
||||
style: cellStyle.primaryTextStyle(),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -72,16 +72,17 @@ class MobileCardContent<CustomCardData> extends StatelessWidget {
|
||||
DatabaseCellContext cellContext,
|
||||
) {
|
||||
final renderHook = RowCardRenderHook<String>();
|
||||
renderHook.addTextCellHook((cellData, _, __) {
|
||||
renderHook.addTextCellHook((cellData, cardData, __) {
|
||||
return BlocBuilder<TextCellBloc, TextCellState>(
|
||||
builder: (context, state) {
|
||||
final text = cellData.isEmpty
|
||||
final cardDataIsEmpty = cardData == null;
|
||||
final text = cardDataIsEmpty
|
||||
? LocaleKeys.grid_row_titlePlaceholder.tr()
|
||||
: cellData;
|
||||
|
||||
final textStyle = Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: cellData.isEmpty
|
||||
? Theme.of(context).colorScheme.onSecondary
|
||||
color: cardDataIsEmpty
|
||||
? Theme.of(context).hintColor
|
||||
: Theme.of(context).colorScheme.onBackground,
|
||||
fontSize: 20,
|
||||
);
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
@ -5,13 +6,22 @@ Future<T?> showFlowyMobileBottomSheet<T>(
|
||||
BuildContext context, {
|
||||
required String title,
|
||||
required Widget Function(BuildContext) builder,
|
||||
bool resizeToAvoidBottomInset = true,
|
||||
bool isScrollControlled = false,
|
||||
}) async {
|
||||
return showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: isScrollControlled,
|
||||
builder: (context) => Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: Corners.s12Radius,
|
||||
),
|
||||
),
|
||||
builder: (context) {
|
||||
const padding = EdgeInsets.fromLTRB(16, 16, 16, 48);
|
||||
|
||||
final child = Padding(
|
||||
padding: padding,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@ -22,7 +32,19 @@ Future<T?> showFlowyMobileBottomSheet<T>(
|
||||
builder(context),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (resizeToAvoidBottomInset) {
|
||||
return AnimatedPadding(
|
||||
padding: padding +
|
||||
EdgeInsets.only(
|
||||
bottom: MediaQuery.of(context).viewInsets.bottom,
|
||||
),
|
||||
duration: Duration.zero,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
return child;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/user/application/sign_in_bloc.dart';
|
||||
import 'package:appflowy/user/presentation/presentation.dart';
|
||||
import 'package:appflowy/util/platform_extension.dart';
|
||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
@ -76,9 +77,40 @@ class _ThirdPartySignInButton extends StatelessWidget {
|
||||
|
||||
final VoidCallback onPressed;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (PlatformExtension.isMobile) {
|
||||
return _MobileSignInButton(
|
||||
icon: icon,
|
||||
labelText: labelText,
|
||||
onPressed: onPressed,
|
||||
);
|
||||
} else {
|
||||
return _DesktopSignInButton(
|
||||
icon: icon,
|
||||
labelText: labelText,
|
||||
onPressed: onPressed,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _DesktopSignInButton extends StatelessWidget {
|
||||
const _DesktopSignInButton({
|
||||
required this.icon,
|
||||
required this.labelText,
|
||||
required this.onPressed,
|
||||
});
|
||||
|
||||
final FlowySvgData icon;
|
||||
final String labelText;
|
||||
|
||||
final VoidCallback onPressed;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final style = Theme.of(context);
|
||||
// In desktop, the width of button is limited by [AuthFormContainer]
|
||||
return SizedBox(
|
||||
height: 48,
|
||||
width: AuthFormContainer.width,
|
||||
@ -130,6 +162,68 @@ class _ThirdPartySignInButton extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _MobileSignInButton extends StatelessWidget {
|
||||
const _MobileSignInButton({
|
||||
required this.icon,
|
||||
required this.labelText,
|
||||
required this.onPressed,
|
||||
});
|
||||
|
||||
final FlowySvgData icon;
|
||||
final String labelText;
|
||||
final VoidCallback onPressed;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final style = Theme.of(context);
|
||||
return GestureDetector(
|
||||
onTap: onPressed,
|
||||
child: Container(
|
||||
height: 48,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(4),
|
||||
),
|
||||
border: Border.all(
|
||||
color: style.colorScheme.outline,
|
||||
width: 0.5,
|
||||
),
|
||||
),
|
||||
child: Center(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
// The icon could be in different height as original aspect ratio, we use a fixed sizebox to wrap it to make sure they all occupy the same space.
|
||||
width: 30,
|
||||
height: 30,
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
child: FlowySvg(
|
||||
icon,
|
||||
blendMode: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const HSpace(8),
|
||||
SizedBox(
|
||||
// To fit the longest label 'Log in with Discord'
|
||||
width: 135,
|
||||
child: Text(
|
||||
labelText,
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _signInWithGoogle(BuildContext context) {
|
||||
context.read<SignInBloc>().add(
|
||||
const SignInEvent.signedInWithOAuth('google'),
|
||||
|
@ -10,6 +10,7 @@ class MobileAppearance extends BaseAppearance {
|
||||
static const _onBackgroundColor = Color(0xff2F3030); // text/title color
|
||||
static const _onSurfaceColor = Color(0xff676666); // text/body color
|
||||
static const _onSecondaryColor = Color(0xFFC5C7CB); // text/body2 color
|
||||
static const _hintColorInDarkMode = Color(0xff626262); // hint color
|
||||
|
||||
@override
|
||||
ThemeData getThemeData(
|
||||
@ -60,13 +61,14 @@ class MobileAppearance extends BaseAppearance {
|
||||
primary: _primaryColor,
|
||||
onPrimary: Colors.white,
|
||||
// TODO(yijing): add color later
|
||||
secondary: Colors.black,
|
||||
secondary: const Color(0xff2d2d2d), //temp
|
||||
onSecondary: Colors.white,
|
||||
tertiary: const Color(0xff858585), // temp
|
||||
error: const Color(0xffFB006D),
|
||||
onError: const Color(0xffFB006D),
|
||||
background: const Color(0xff1C1C1E), // BG/Secondary color
|
||||
background: const Color(0xff121212), // temp
|
||||
onBackground: Colors.white,
|
||||
outline: const Color(0xff96989C), //caption
|
||||
outline: _hintColorInDarkMode,
|
||||
outlineVariant: Colors.black,
|
||||
//Snack bar
|
||||
surface: const Color(0xff2F3030),
|
||||
@ -75,7 +77,7 @@ class MobileAppearance extends BaseAppearance {
|
||||
|
||||
final hintColor = brightness == Brightness.light
|
||||
? const Color(0xff89909B)
|
||||
: const Color(0xff96989C);
|
||||
: _hintColorInDarkMode;
|
||||
|
||||
return ThemeData(
|
||||
// color
|
||||
|
Loading…
Reference in New Issue
Block a user