feat: support editing database icon (#4052)

This commit is contained in:
Lucas.Xu 2023-11-30 16:56:44 +08:00 committed by GitHub
parent b307dd30d8
commit d7a67c0efb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 143 additions and 62 deletions

View File

@ -304,7 +304,7 @@ class _SingleMobileInnerViewItemState extends State<SingleMobileInnerViewItem> {
_buildLeftIcon(), _buildLeftIcon(),
const HSpace(4), const HSpace(4),
// icon // icon
_buildViewIconButton(), _buildViewIcon(),
const HSpace(8), const HSpace(8),
// title // title
Expanded( Expanded(
@ -354,7 +354,7 @@ class _SingleMobileInnerViewItemState extends State<SingleMobileInnerViewItem> {
return child; return child;
} }
Widget _buildViewIconButton() { Widget _buildViewIcon() {
final icon = widget.view.icon.value.isNotEmpty final icon = widget.view.icon.value.isNotEmpty
? EmojiText( ? EmojiText(
emoji: widget.view.icon.value, emoji: widget.view.icon.value,

View File

@ -1,13 +1,36 @@
import 'package:appflowy/plugins/base/emoji/emoji_picker_screen.dart';
import 'package:appflowy/plugins/base/emoji/emoji_text.dart';
import 'package:appflowy/plugins/base/icon/icon_picker.dart';
import 'package:appflowy/plugins/database_view/application/tab_bar_bloc.dart'; import 'package:appflowy/plugins/database_view/application/tab_bar_bloc.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/grid_page.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/grid_page.dart';
import 'package:appflowy/plugins/database_view/widgets/setting/mobile_database_settings_button.dart'; import 'package:appflowy/plugins/database_view/widgets/setting/mobile_database_settings_button.dart';
import 'package:appflowy/workspace/application/view/view_bloc.dart';
import 'package:appflowy/workspace/application/view/view_ext.dart';
import 'package:appflowy/workspace/application/view/view_service.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.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:go_router/go_router.dart';
class MobileTabBarHeader extends StatelessWidget { class MobileTabBarHeader extends StatefulWidget {
const MobileTabBarHeader({super.key}); const MobileTabBarHeader({super.key});
@override
State<MobileTabBarHeader> createState() => _MobileTabBarHeaderState();
}
class _MobileTabBarHeaderState extends State<MobileTabBarHeader> {
final controller = TextEditingController();
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<DatabaseTabBarBloc, DatabaseTabBarState>( return BlocBuilder<DatabaseTabBarBloc, DatabaseTabBarState>(
@ -20,6 +43,8 @@ class MobileTabBarHeader extends StatelessWidget {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
controller.text = currentView.view.name;
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -27,11 +52,31 @@ class MobileTabBarHeader extends StatelessWidget {
padding: const EdgeInsets.symmetric(vertical: 14), padding: const EdgeInsets.symmetric(vertical: 14),
child: Row( child: Row(
children: [ children: [
_buildViewIconButton(currentView.view),
const HSpace(8.0),
Expanded( Expanded(
child: Text( child: FlowyTextField(
currentView.view.name, autoFocus: false,
style: Theme.of(context).textTheme.titleLarge, maxLines: null,
overflow: TextOverflow.ellipsis, controller: controller,
textAlignVertical: TextAlignVertical.top,
decoration: const InputDecoration(
border: InputBorder.none,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
contentPadding: EdgeInsets.zero,
),
textStyle: Theme.of(context).textTheme.titleLarge,
onSubmitted: (value) {
if (value.isNotEmpty) {
context.read<ViewBloc>().add(
ViewEvent.rename(value),
);
}
},
onCanceled: () {
controller.text = currentView.view.name;
},
), ),
), ),
MobileDatabaseSettingsButton( MobileDatabaseSettingsButton(
@ -43,10 +88,40 @@ class MobileTabBarHeader extends StatelessWidget {
], ],
), ),
), ),
const Divider(height: 1, thickness: 1), const Divider(
height: 1,
thickness: 1,
),
], ],
); );
}, },
); );
} }
Widget _buildViewIconButton(ViewPB view) {
final icon = view.icon.value.isNotEmpty
? EmojiText(
emoji: view.icon.value,
fontSize: 24.0,
)
: SizedBox.square(
dimension: 26.0,
child: view.defaultIcon(),
);
return FlowyButton(
text: icon,
useIntrinsicWidth: true,
onTap: () async {
final result = await context.push<EmojiPickerResult>(
MobileEmojiPickerScreen.routeName,
);
if (context.mounted && result != null) {
await ViewBackendService.updateViewIcon(
viewId: view.id,
viewIcon: result.emoji,
);
}
},
);
}
} }

View File

@ -20,7 +20,7 @@ class FlowyTextField extends StatefulWidget {
final bool submitOnLeave; final bool submitOnLeave;
final Duration? debounceDuration; final Duration? debounceDuration;
final String? errorText; final String? errorText;
final int maxLines; final int? maxLines;
final bool showCounter; final bool showCounter;
final Widget? prefixIcon; final Widget? prefixIcon;
final Widget? suffixIcon; final Widget? suffixIcon;
@ -28,6 +28,8 @@ class FlowyTextField extends StatefulWidget {
final BoxConstraints? suffixIconConstraints; final BoxConstraints? suffixIconConstraints;
final BoxConstraints? hintTextConstraints; final BoxConstraints? hintTextConstraints;
final TextStyle? hintStyle; final TextStyle? hintStyle;
final InputDecoration? decoration;
final TextAlignVertical? textAlignVertical;
const FlowyTextField({ const FlowyTextField({
super.key, super.key,
@ -54,6 +56,8 @@ class FlowyTextField extends StatefulWidget {
this.suffixIconConstraints, this.suffixIconConstraints,
this.hintTextConstraints, this.hintTextConstraints,
this.hintStyle, this.hintStyle,
this.decoration,
this.textAlignVertical,
}); });
@override @override
@ -130,64 +134,66 @@ class FlowyTextFieldState extends State<FlowyTextField> {
maxLength: widget.maxLength, maxLength: widget.maxLength,
maxLengthEnforcement: MaxLengthEnforcement.truncateAfterCompositionEnds, maxLengthEnforcement: MaxLengthEnforcement.truncateAfterCompositionEnds,
style: widget.textStyle ?? Theme.of(context).textTheme.bodySmall, style: widget.textStyle ?? Theme.of(context).textTheme.bodySmall,
textAlignVertical: TextAlignVertical.center, textAlignVertical: widget.textAlignVertical ?? TextAlignVertical.center,
keyboardType: TextInputType.multiline, keyboardType: TextInputType.multiline,
decoration: InputDecoration( decoration: widget.decoration ??
constraints: widget.hintTextConstraints ?? InputDecoration(
BoxConstraints( constraints: widget.hintTextConstraints ??
maxHeight: widget.errorText?.isEmpty ?? true ? 32 : 58, BoxConstraints(
maxHeight: widget.errorText?.isEmpty ?? true ? 32 : 58,
),
contentPadding: EdgeInsets.symmetric(
horizontal: 12,
vertical:
(widget.maxLines == null || widget.maxLines! > 1) ? 12 : 0,
), ),
contentPadding: EdgeInsets.symmetric( enabledBorder: OutlineInputBorder(
horizontal: 12, borderSide: BorderSide(
vertical: widget.maxLines > 1 ? 12 : 0, color: Theme.of(context).colorScheme.outline,
), width: 1.0,
enabledBorder: OutlineInputBorder( ),
borderSide: BorderSide( borderRadius: Corners.s8Border,
color: Theme.of(context).colorScheme.outline, ),
width: 1.0, isDense: false,
), hintText: widget.hintText,
borderRadius: Corners.s8Border, errorText: widget.errorText,
), errorStyle: Theme.of(context)
isDense: false,
hintText: widget.hintText,
errorText: widget.errorText,
errorStyle: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(color: Theme.of(context).colorScheme.error),
hintStyle: widget.hintStyle ??
Theme.of(context)
.textTheme .textTheme
.bodySmall! .bodySmall!
.copyWith(color: Theme.of(context).hintColor), .copyWith(color: Theme.of(context).colorScheme.error),
suffixText: widget.showCounter ? _suffixText() : "", hintStyle: widget.hintStyle ??
counterText: "", Theme.of(context)
focusedBorder: OutlineInputBorder( .textTheme
borderSide: BorderSide( .bodySmall!
color: Theme.of(context).colorScheme.primary, .copyWith(color: Theme.of(context).hintColor),
width: 1.0, suffixText: widget.showCounter ? _suffixText() : "",
counterText: "",
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.primary,
width: 1.0,
),
borderRadius: Corners.s8Border,
),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.error,
width: 1.0,
),
borderRadius: Corners.s8Border,
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.error,
width: 1.0,
),
borderRadius: Corners.s8Border,
),
prefixIcon: widget.prefixIcon,
suffixIcon: widget.suffixIcon,
prefixIconConstraints: widget.prefixIconConstraints,
suffixIconConstraints: widget.suffixIconConstraints,
), ),
borderRadius: Corners.s8Border,
),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.error,
width: 1.0,
),
borderRadius: Corners.s8Border,
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.error,
width: 1.0,
),
borderRadius: Corners.s8Border,
),
prefixIcon: widget.prefixIcon,
suffixIcon: widget.suffixIcon,
prefixIconConstraints: widget.prefixIconConstraints,
suffixIconConstraints: widget.suffixIconConstraints,
),
); );
} }