mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
[flutter]: modify view's name in topbar
This commit is contained in:
parent
ec920e430c
commit
4f41c8d3e5
@ -61,14 +61,22 @@ class FlowyNavigation extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
update: (_, notifier, controller) => controller!..update(notifier),
|
||||
child: Row(children: [
|
||||
Selector<NavigationNotifier, PublishNotifier<bool>>(
|
||||
selector: (context, notifier) => notifier.collapasedNotifier,
|
||||
builder: (ctx, collapsedNotifier, child) => _renderCollapse(ctx, collapsedNotifier)),
|
||||
Selector<NavigationNotifier, List<NavigationItem>>(
|
||||
child: Expanded(
|
||||
child: Row(children: [
|
||||
Selector<NavigationNotifier, PublishNotifier<bool>>(
|
||||
selector: (context, notifier) => notifier.collapasedNotifier,
|
||||
builder: (ctx, collapsedNotifier, child) => _renderCollapse(ctx, collapsedNotifier)),
|
||||
Selector<NavigationNotifier, List<NavigationItem>>(
|
||||
selector: (context, notifier) => notifier.navigationItems,
|
||||
builder: (ctx, items, child) => Row(children: _renderNavigationItems(items))),
|
||||
]),
|
||||
builder: (ctx, items, child) => Expanded(
|
||||
child: Wrap(
|
||||
children: _renderNavigationItems(items),
|
||||
crossAxisAlignment: WrapCrossAlignment.start,
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -106,7 +114,13 @@ class FlowyNavigation extends StatelessWidget {
|
||||
Widget last = NaviItemWidget(newItems.removeLast());
|
||||
|
||||
List<Widget> widgets = List.empty(growable: true);
|
||||
widgets.addAll(newItems.map((item) => NaviItemDivider(child: NaviItemWidget(item))).toList());
|
||||
// widgets.addAll(newItems.map((item) => NaviItemDivider(child: NaviItemWidget(item))).toList());
|
||||
|
||||
for (final item in newItems) {
|
||||
widgets.add(NaviItemWidget(item));
|
||||
widgets.add(const Text('/'));
|
||||
}
|
||||
|
||||
widgets.add(last);
|
||||
|
||||
return widgets;
|
||||
@ -129,39 +143,13 @@ class FlowyNavigation extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class IconNaviItemWidget extends StatelessWidget {
|
||||
final NavigationItem item;
|
||||
const IconNaviItemWidget(this.item, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 24,
|
||||
child: InkWell(
|
||||
child: item.leftBarItem,
|
||||
onTap: () {
|
||||
debugPrint('show app document');
|
||||
},
|
||||
).padding(horizontal: 8, vertical: 2),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NaviItemWidget extends StatelessWidget {
|
||||
final NavigationItem item;
|
||||
const NaviItemWidget(this.item, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 24,
|
||||
child: InkWell(
|
||||
child: item.leftBarItem,
|
||||
onTap: () {
|
||||
debugPrint('show app document');
|
||||
},
|
||||
).padding(horizontal: 8, vertical: 2),
|
||||
);
|
||||
return item.leftBarItem.padding(horizontal: 2, vertical: 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,7 +160,7 @@ class NaviItemDivider extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [child, const Text('/').padding(horizontal: 2)],
|
||||
children: [child, const Text('/')],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,15 @@ import 'package:app_flowy/workspace/application/doc/share_bloc.dart';
|
||||
import 'package:app_flowy/workspace/domain/i_view.dart';
|
||||
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
|
||||
import 'package:app_flowy/workspace/domain/view_ext.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart';
|
||||
import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart';
|
||||
import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra/theme.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
||||
import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
|
||||
import 'package:flowy_log/flowy_log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/export.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart';
|
||||
@ -40,7 +43,7 @@ class DocStackContext extends HomeStackContext<String, ShareActionWrapper> {
|
||||
}
|
||||
|
||||
@override
|
||||
Widget get leftBarItem => FlowyText.medium(_view.name, fontSize: 12);
|
||||
Widget get leftBarItem => DocLeftBarItem(view: _view);
|
||||
|
||||
@override
|
||||
Widget? get rightBarItem => DocShareButton(view: _view);
|
||||
@ -65,7 +68,9 @@ class DocStackContext extends HomeStackContext<String, ShareActionWrapper> {
|
||||
// }).toList();
|
||||
|
||||
List<NavigationItem> _makeNavigationItems() {
|
||||
return [this];
|
||||
return [
|
||||
this,
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
@ -74,6 +79,74 @@ class DocStackContext extends HomeStackContext<String, ShareActionWrapper> {
|
||||
}
|
||||
}
|
||||
|
||||
class DocLeftBarItem extends StatefulWidget {
|
||||
final View view;
|
||||
|
||||
const DocLeftBarItem({required this.view, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<DocLeftBarItem> createState() => _DocLeftBarItemState();
|
||||
}
|
||||
|
||||
class _DocLeftBarItemState extends State<DocLeftBarItem> {
|
||||
final _controller = TextEditingController();
|
||||
final _focusNode = FocusNode();
|
||||
late ViewRepository repo;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
repo = ViewRepository(view: widget.view);
|
||||
_focusNode.addListener(_handleFocusChanged);
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
_focusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_controller.text = widget.view.name;
|
||||
|
||||
final theme = context.watch<AppTheme>();
|
||||
return IntrinsicWidth(
|
||||
child: TextField(
|
||||
controller: _controller,
|
||||
focusNode: _focusNode,
|
||||
scrollPadding: EdgeInsets.zero,
|
||||
decoration: const InputDecoration(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
border: InputBorder.none,
|
||||
isDense: true,
|
||||
),
|
||||
style: TextStyle(
|
||||
color: theme.shader1,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
// cursorColor: widget.cursorColor,
|
||||
// obscureText: widget.enableObscure,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _handleFocusChanged() {
|
||||
if (_controller.text.isEmpty) {
|
||||
_controller.text = widget.view.name;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_controller.text != widget.view.name) {
|
||||
repo.updateView(name: _controller.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DocShareButton extends StatelessWidget {
|
||||
final View view;
|
||||
DocShareButton({Key? key, required this.view}) : super(key: ValueKey(view.id));
|
||||
|
@ -21,7 +21,7 @@ class HomeTopBar extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const FlowyNavigation(),
|
||||
const Spacer(),
|
||||
const HSpace(16),
|
||||
ChangeNotifierProvider.value(
|
||||
value: Provider.of<HomeStackNotifier>(context, listen: false),
|
||||
child: Consumer(
|
||||
|
@ -10,8 +10,7 @@ import 'package:provider/provider.dart';
|
||||
import 'package:textstyle_extensions/textstyle_extensions.dart';
|
||||
|
||||
class FlowyFormTextInput extends StatelessWidget {
|
||||
static EdgeInsets kDefaultTextInputPadding =
|
||||
EdgeInsets.only(bottom: Insets.sm, top: 4);
|
||||
static EdgeInsets kDefaultTextInputPadding = EdgeInsets.only(bottom: Insets.sm, top: 4);
|
||||
|
||||
final String? label;
|
||||
final bool? autoFocus;
|
||||
@ -61,8 +60,7 @@ class FlowyFormTextInput extends StatelessWidget {
|
||||
inputDecoration: InputDecoration(
|
||||
isDense: true,
|
||||
contentPadding: contentPadding ?? kDefaultTextInputPadding,
|
||||
border: const ThinUnderlineBorder(
|
||||
borderSide: BorderSide(width: 5, color: Colors.red)),
|
||||
border: const ThinUnderlineBorder(borderSide: BorderSide(width: 5, color: Colors.red)),
|
||||
//focusedBorder: UnderlineInputBorder(borderSide: BorderSide(width: .5, color: Colors.red)),
|
||||
hintText: hintText,
|
||||
),
|
||||
@ -143,8 +141,7 @@ class StyledSearchTextInputState extends State<StyledSearchTextInput> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_controller =
|
||||
widget.controller ?? TextEditingController(text: widget.initialValue);
|
||||
_controller = widget.controller ?? TextEditingController(text: widget.initialValue);
|
||||
_focusNode = FocusNode(
|
||||
debugLabel: widget.label ?? '',
|
||||
onKey: (FocusNode node, RawKeyEvent evt) {
|
||||
@ -160,8 +157,7 @@ class StyledSearchTextInputState extends State<StyledSearchTextInput> {
|
||||
canRequestFocus: true,
|
||||
);
|
||||
// Listen for focus out events
|
||||
_focusNode
|
||||
.addListener(() => widget.onFocusChanged?.call(_focusNode.hasFocus));
|
||||
_focusNode.addListener(() => widget.onFocusChanged?.call(_focusNode.hasFocus));
|
||||
widget.onFocusCreated?.call(_focusNode);
|
||||
if (widget.autoFocus ?? false) {
|
||||
scheduleMicrotask(() => _focusNode.requestFocus());
|
||||
@ -210,8 +206,7 @@ class StyledSearchTextInputState extends State<StyledSearchTextInput> {
|
||||
InputDecoration(
|
||||
prefixIcon: widget.prefixIcon,
|
||||
suffixIcon: widget.suffixIcon,
|
||||
contentPadding:
|
||||
widget.contentPadding ?? EdgeInsets.all(Insets.m),
|
||||
contentPadding: widget.contentPadding ?? EdgeInsets.all(Insets.m),
|
||||
border: const OutlineInputBorder(borderSide: BorderSide.none),
|
||||
isDense: true,
|
||||
icon: widget.icon == null ? null : Icon(widget.icon),
|
||||
@ -259,8 +254,7 @@ class ThinUnderlineBorder extends InputBorder {
|
||||
bool get isOutline => false;
|
||||
|
||||
@override
|
||||
UnderlineInputBorder copyWith(
|
||||
{BorderSide? borderSide, BorderRadius? borderRadius}) {
|
||||
UnderlineInputBorder copyWith({BorderSide? borderSide, BorderRadius? borderRadius}) {
|
||||
return UnderlineInputBorder(
|
||||
borderSide: borderSide ?? this.borderSide,
|
||||
borderRadius: borderRadius ?? this.borderRadius,
|
||||
@ -280,8 +274,7 @@ class ThinUnderlineBorder extends InputBorder {
|
||||
@override
|
||||
Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
|
||||
return Path()
|
||||
..addRect(Rect.fromLTWH(rect.left, rect.top, rect.width,
|
||||
math.max(0.0, rect.height - borderSide.width)));
|
||||
..addRect(Rect.fromLTWH(rect.left, rect.top, rect.width, math.max(0.0, rect.height - borderSide.width)));
|
||||
}
|
||||
|
||||
@override
|
||||
@ -292,8 +285,7 @@ class ThinUnderlineBorder extends InputBorder {
|
||||
@override
|
||||
ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
|
||||
if (a is UnderlineInputBorder) {
|
||||
final newBorderRadius =
|
||||
BorderRadius.lerp(a.borderRadius, borderRadius, t);
|
||||
final newBorderRadius = BorderRadius.lerp(a.borderRadius, borderRadius, t);
|
||||
|
||||
if (newBorderRadius != null) {
|
||||
return UnderlineInputBorder(
|
||||
@ -308,8 +300,7 @@ class ThinUnderlineBorder extends InputBorder {
|
||||
@override
|
||||
ShapeBorder? lerpTo(ShapeBorder? b, double t) {
|
||||
if (b is UnderlineInputBorder) {
|
||||
final newBorderRadius =
|
||||
BorderRadius.lerp(b.borderRadius, borderRadius, t);
|
||||
final newBorderRadius = BorderRadius.lerp(b.borderRadius, borderRadius, t);
|
||||
if (newBorderRadius != null) {
|
||||
return UnderlineInputBorder(
|
||||
borderSide: BorderSide.lerp(borderSide, b.borderSide, t),
|
||||
@ -335,8 +326,7 @@ class ThinUnderlineBorder extends InputBorder {
|
||||
double gapPercentage = 0.0,
|
||||
TextDirection? textDirection,
|
||||
}) {
|
||||
if (borderRadius.bottomLeft != Radius.zero ||
|
||||
borderRadius.bottomRight != Radius.zero) {
|
||||
if (borderRadius.bottomLeft != Radius.zero || borderRadius.bottomRight != Radius.zero) {
|
||||
canvas.clipPath(getOuterPath(rect, textDirection: textDirection));
|
||||
}
|
||||
canvas.drawLine(rect.bottomLeft, rect.bottomRight, borderSide.toPaint());
|
||||
|
@ -17,12 +17,15 @@ class RoundedInputField extends StatefulWidget {
|
||||
final String errorText;
|
||||
final TextStyle style;
|
||||
final ValueChanged<String>? onChanged;
|
||||
final String? initialValue;
|
||||
late bool enableObscure;
|
||||
var _text = "";
|
||||
|
||||
RoundedInputField({
|
||||
Key? key,
|
||||
this.hintText,
|
||||
this.errorText = "",
|
||||
this.initialValue,
|
||||
this.icon,
|
||||
this.obscureText = false,
|
||||
this.obscureIcon,
|
||||
@ -32,7 +35,6 @@ class RoundedInputField extends StatefulWidget {
|
||||
this.highlightBorderColor = Colors.transparent,
|
||||
this.cursorColor = Colors.black,
|
||||
this.style = const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
|
||||
this.errorText = "",
|
||||
}) : super(key: key) {
|
||||
enableObscure = obscureText;
|
||||
}
|
||||
@ -62,6 +64,7 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
|
||||
borderRadius: Corners.s10Border,
|
||||
borderColor: borderColor,
|
||||
child: TextFormField(
|
||||
initialValue: widget.initialValue,
|
||||
onChanged: (value) {
|
||||
widget._text = value;
|
||||
if (widget.onChanged != null) {
|
||||
|
Loading…
Reference in New Issue
Block a user