[flutter]: config home screen question bubble

This commit is contained in:
appflowy 2021-11-06 19:45:23 +08:00
parent 7246f597af
commit f1251e7152
16 changed files with 265 additions and 70 deletions

View File

@ -2,9 +2,14 @@ import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:dartz/dartz.dart' as dartz;
import 'package:styled_widget/styled_widget.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';
class QuestionBubble extends StatelessWidget {
const QuestionBubble({Key? key}) : super(key: key);
@ -17,22 +22,45 @@ class QuestionBubble extends StatelessWidget {
height: 30,
child: FlowyTextButton(
'?',
tooltip: QuestionBubbleAction.values.map((action) => action.name).toList().join(','),
fontSize: 12,
fontWeight: FontWeight.w600,
fillColor: theme.selector,
mainAxisAlignment: MainAxisAlignment.center,
radius: BorderRadius.circular(10),
onPressed: () {
final actionList = QuestionBubbleActions(onSelected: (action) {});
final actionList = QuestionBubbleActions(onSelected: (result) {
result.fold(() {}, (action) {
switch (action) {
case QuestionBubbleAction.whatsNews:
// TODO: annie replace the URL with real ones
_launchURL("https://www.google.com");
break;
case QuestionBubbleAction.help:
// TODO: annie replace the URL with real ones
_launchURL("https://www.google.com");
break;
}
});
});
actionList.show(
context,
context,
anchorDirection: AnchorDirection.topWithCenterAligned,
anchorDirection: AnchorDirection.topWithRightAligned,
anchorOffset: const Offset(0, -10),
);
},
),
);
}
_launchURL(String url) async {
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
}
class QuestionBubbleActions with ActionList<QuestionBubbleActionWrapper> implements FlowyOverlayDelegate {
@ -43,6 +71,12 @@ class QuestionBubbleActions with ActionList<QuestionBubbleActionWrapper> impleme
required this.onSelected,
});
@override
double get maxWidth => 170;
@override
double get itemHeight => 22;
@override
List<QuestionBubbleActionWrapper> get items => _items;
@ -63,10 +97,57 @@ class QuestionBubbleActions with ActionList<QuestionBubbleActionWrapper> impleme
void didRemove() {
onSelected(dartz.none());
}
@override
ListOverlayFooter? get footer => ListOverlayFooter(
widget: const FlowyVersionDescription(),
height: 30,
padding: const EdgeInsets.only(top: 6),
);
}
class FlowyVersionDescription extends StatelessWidget {
const FlowyVersionDescription({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return FutureBuilder(
future: PackageInfo.fromPlatform(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return FlowyText("Error: ${snapshot.error}", fontSize: 12, color: theme.shader4);
}
PackageInfo packageInfo = snapshot.data;
String appName = packageInfo.appName;
String version = packageInfo.version;
String buildNumber = packageInfo.buildNumber;
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Divider(height: 1, color: theme.shader6, thickness: 1.0),
const VSpace(6),
FlowyText("$appName $version.$buildNumber", fontSize: 12, color: theme.shader4),
],
).padding(
horizontal: ActionListSizes.itemHPadding + ActionListSizes.padding,
);
} else {
return const CircularProgressIndicator();
}
},
);
}
}
enum QuestionBubbleAction {
whatsNews,
help,
}
class QuestionBubbleActionWrapper extends ActionItemData {
@ -74,7 +155,7 @@ class QuestionBubbleActionWrapper extends ActionItemData {
QuestionBubbleActionWrapper(this.inner);
@override
Widget? get icon => null;
Widget? get icon => inner.emoji;
@override
String get name => inner.name;
@ -85,6 +166,17 @@ extension QuestionBubbleExtension on QuestionBubbleAction {
switch (this) {
case QuestionBubbleAction.whatsNews:
return "What's new";
case QuestionBubbleAction.help:
return "Help & Support";
}
}
Widget get emoji {
switch (this) {
case QuestionBubbleAction.whatsNews:
return const Text('😘', style: TextStyle(fontSize: 16));
case QuestionBubbleAction.help:
return const Text('💁🏻', style: TextStyle(fontSize: 16));
}
}
}

View File

@ -55,8 +55,8 @@ class ActionList {
itemBuilder: (context, index) => items[index],
anchorContext: anchorContext,
anchorDirection: AnchorDirection.bottomRight,
maxWidth: 120,
maxHeight: 80,
width: 120,
height: 80,
);
}
}

View File

@ -3,6 +3,7 @@ import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart';
import 'package:dartz/dartz.dart' as dartz;
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:tuple/tuple.dart';
class AppDisclosureActions with ActionList<AppDisclosureActionWrapper> implements FlowyOverlayDelegate {
final Function(dartz.Option<AppDisclosureAction>) onSelected;
@ -32,6 +33,9 @@ class AppDisclosureActions with ActionList<AppDisclosureActionWrapper> implement
void didRemove() {
onSelected(dartz.none());
}
@override
ListOverlayFooter? get footer => null;
}
class AppDisclosureActionWrapper extends ActionItemData {
@ -39,7 +43,7 @@ class AppDisclosureActionWrapper extends ActionItemData {
AppDisclosureActionWrapper(this.inner);
@override
Widget get icon => inner.icon;
Widget? get icon => inner.icon;
@override
String get name => inner.name;

View File

@ -5,6 +5,7 @@ import 'package:flowy_infra/image.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
import 'package:flutter/material.dart';
import 'package:tuple/tuple.dart';
// [[Widget: LifeCycle]]
// https://flutterbyexample.com/lesson/stateful-widget-lifecycle
@ -37,9 +38,6 @@ class ViewDisclosureButton extends StatelessWidget
@override
List<ViewDisclosureActionWrapper> get items => _items;
@override
double get maxWidth => 162;
@override
void Function(dartz.Option<ViewDisclosureActionWrapper> p1) get selectCallback => (result) {
result.fold(
@ -55,6 +53,9 @@ class ViewDisclosureButton extends StatelessWidget
void didRemove() {
onSelected(dartz.none());
}
@override
ListOverlayFooter? get footer => null;
}
class ViewDisclosureActionWrapper extends ActionItemData {
@ -62,7 +63,7 @@ class ViewDisclosureActionWrapper extends ActionItemData {
ViewDisclosureActionWrapper(this.inner);
@override
Widget get icon => inner.icon;
Widget? get icon => inner.icon;
@override
String get name => inner.name;

View File

@ -15,23 +15,33 @@ abstract class ActionList<T extends ActionItemData> {
double get maxWidth => 162;
double get itemHeight => ActionListSizes.itemHeight;
ListOverlayFooter? get footer;
void Function(dartz.Option<T>) get selectCallback;
FlowyOverlayDelegate? get delegate;
void show(BuildContext buildContext, BuildContext anchorContext,
{AnchorDirection anchorDirection = AnchorDirection.bottomRight}) {
void show(
BuildContext buildContext,
BuildContext anchorContext, {
AnchorDirection anchorDirection = AnchorDirection.bottomRight,
Offset? anchorOffset,
}) {
final widgets = items
.map((action) => ActionItem<T>(
.map(
(action) => ActionItem<T>(
action: action,
itemHeight: itemHeight,
onSelected: (action) {
FlowyOverlay.of(buildContext).remove(identifier);
selectCallback(dartz.some(action));
}))
},
),
)
.toList();
double totalHeight = widgets.length * (ActionListSizes.itemHeight + ActionListSizes.padding * 2);
ListOverlay.showWithAnchor(
buildContext,
identifier: identifier,
@ -39,9 +49,11 @@ abstract class ActionList<T extends ActionItemData> {
itemBuilder: (context, index) => widgets[index],
anchorContext: anchorContext,
anchorDirection: anchorDirection,
maxWidth: maxWidth,
maxHeight: totalHeight,
width: maxWidth,
height: widgets.length * (itemHeight + ActionListSizes.padding * 2),
delegate: delegate,
anchorOffset: anchorOffset,
footer: footer,
);
}
}
@ -60,10 +72,12 @@ class ActionListSizes {
class ActionItem<T extends ActionItemData> extends StatelessWidget {
final T action;
final Function(T) onSelected;
final double itemHeight;
const ActionItem({
Key? key,
required this.action,
required this.onSelected,
required this.itemHeight,
}) : super(key: key);
@override
@ -77,7 +91,7 @@ class ActionItem<T extends ActionItemData> extends StatelessWidget {
behavior: HitTestBehavior.opaque,
onTap: () => onSelected(action),
child: SizedBox(
height: ActionListSizes.itemHeight,
height: itemHeight,
child: Row(
children: [
if (action.icon != null) action.icon!,

View File

@ -8,6 +8,7 @@ import Foundation
import flowy_editor
import flowy_infra_ui
import flowy_sdk
import package_info_plus_macos
import path_provider_macos
import url_launcher_macos
import window_size
@ -16,6 +17,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlowyEditorPlugin.register(with: registry.registrar(forPlugin: "FlowyEditorPlugin"))
FlowyInfraUIPlugin.register(with: registry.registrar(forPlugin: "FlowyInfraUIPlugin"))
FlowySdkPlugin.register(with: registry.registrar(forPlugin: "FlowySdkPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
WindowSizePlugin.register(with: registry.registrar(forPlugin: "WindowSizePlugin"))

View File

@ -6,6 +6,8 @@ PODS:
- flowy_sdk (0.0.1):
- FlutterMacOS
- FlutterMacOS (1.0.0)
- package_info_plus_macos (0.0.1):
- FlutterMacOS
- path_provider_macos (0.0.1):
- FlutterMacOS
- url_launcher_macos (0.0.1):
@ -18,6 +20,7 @@ DEPENDENCIES:
- flowy_infra_ui (from `Flutter/ephemeral/.symlinks/plugins/flowy_infra_ui/macos`)
- flowy_sdk (from `Flutter/ephemeral/.symlinks/plugins/flowy_sdk/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- package_info_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos`)
- path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
- window_size (from `Flutter/ephemeral/.symlinks/plugins/window_size/macos`)
@ -31,6 +34,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/flowy_sdk/macos
FlutterMacOS:
:path: Flutter/ephemeral
package_info_plus_macos:
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos
path_provider_macos:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos
url_launcher_macos:
@ -43,6 +48,7 @@ SPEC CHECKSUMS:
flowy_infra_ui: 9d5021b1610fe0476eb1191bf7cd41c4a4138d8f
flowy_sdk: c302ac0a22dea596db0df8073b9637b2bf2ff6fd
FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424
package_info_plus_macos: f010621b07802a241d96d01876d6705f15e77c1c
path_provider_macos: 160cab0d5461f0c0e02995469a98f24bdb9a3f1f
url_launcher_macos: 45af3d61de06997666568a7149c1be98b41c95d4
window_size: 339dafa0b27a95a62a843042038fa6c3c48de195

View File

@ -57,7 +57,7 @@
1CD81A6C7244B2318E0BA2E8 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
33CC10ED2044A3C60003C045 /* app_flowy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = app_flowy.app; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10ED2044A3C60003C045 /* AppFlowy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AppFlowy.app; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
@ -112,7 +112,7 @@
33CC10EE2044A3C60003C045 /* Products */ = {
isa = PBXGroup;
children = (
33CC10ED2044A3C60003C045 /* app_flowy.app */,
33CC10ED2044A3C60003C045 /* AppFlowy.app */,
);
name = Products;
sourceTree = "<group>";
@ -192,7 +192,7 @@
);
name = Runner;
productName = Runner;
productReference = 33CC10ED2044A3C60003C045 /* app_flowy.app */;
productReference = 33CC10ED2044A3C60003C045 /* AppFlowy.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
@ -425,6 +425,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
PRODUCT_NAME = AppFlowy;
PROVISIONING_PROFILE_SPECIFIER = "";
STRIP_STYLE = "non-global";
SWIFT_VERSION = 5.0;
@ -552,6 +553,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
PRODUCT_NAME = AppFlowy;
PROVISIONING_PROFILE_SPECIFIER = "";
STRIP_STYLE = "non-global";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -573,6 +575,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
PRODUCT_NAME = AppFlowy;
PROVISIONING_PROFILE_SPECIFIER = "";
STRIP_STYLE = "non-global";
SWIFT_VERSION = 5.0;

View File

@ -15,7 +15,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "app_flowy.app"
BuildableName = "AppFlowy.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
@ -31,13 +31,13 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "app_flowy.app"
BuildableName = "AppFlowy.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@ -54,13 +54,11 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "app_flowy.app"
BuildableName = "AppFlowy.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
@ -73,7 +71,7 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "app_flowy.app"
BuildableName = "AppFlowy.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>

View File

@ -188,8 +188,8 @@ class OverlayScreen extends StatelessWidget {
anchorContext: buttonContext,
anchorDirection: providerContext.read<OverlayDemoConfiguration>().anchorDirection,
overlapBehaviour: providerContext.read<OverlayDemoConfiguration>().overlapBehaviour,
maxWidth: 200.0,
maxHeight: 200.0,
width: 200.0,
height: 200.0,
);
},
child: const Text('Show List Overlay'),

View File

@ -163,7 +163,7 @@ class FlowyOverlayState extends State<FlowyOverlay> {
FlowyOverlayDelegate? delegate,
OverlapBehaviour? overlapBehaviour,
FlowyOverlayStyle? style,
Offset? anchorPosition,
Offset? anchorOffset,
}) {
this.style = style ?? FlowyOverlayStyle();
@ -175,7 +175,7 @@ class FlowyOverlayState extends State<FlowyOverlay> {
anchorContext: anchorContext,
anchorDirection: anchorDirection,
overlapBehaviour: overlapBehaviour,
anchorPosition: anchorPosition,
anchorOffset: anchorOffset,
);
}
@ -209,10 +209,12 @@ class FlowyOverlayState extends State<FlowyOverlay> {
Size? anchorSize,
AnchorDirection? anchorDirection,
BuildContext? anchorContext,
Offset? anchorOffset,
OverlapBehaviour? overlapBehaviour,
FlowyOverlayDelegate? delegate,
}) {
Widget overlay = widget;
final offset = anchorOffset ?? Offset.zero;
if (shouldAnchor) {
assert(
@ -232,8 +234,8 @@ class FlowyOverlayState extends State<FlowyOverlay> {
targetAnchorSize = renderBox.size;
}
final anchorRect = Rect.fromLTWH(
targetAnchorPosition.dx,
targetAnchorPosition.dy,
targetAnchorPosition.dx + offset.dx,
targetAnchorPosition.dy + offset.dy,
targetAnchorSize.width,
targetAnchorSize.height,
);

View File

@ -2,38 +2,68 @@ import 'package:flowy_infra_ui/flowy_infra_ui_web.dart';
import 'package:flowy_infra_ui/style_widget/decoration.dart';
import 'package:flutter/material.dart';
class ListOverlayFooter {
Widget widget;
double height;
EdgeInsets padding;
ListOverlayFooter({
required this.widget,
required this.height,
this.padding = EdgeInsets.zero,
});
}
class ListOverlay extends StatelessWidget {
const ListOverlay({
Key? key,
required this.itemBuilder,
this.itemCount,
this.controller,
this.maxWidth = double.infinity,
this.maxHeight = double.infinity,
this.width = double.infinity,
this.height = double.infinity,
this.footer,
}) : super(key: key);
final IndexedWidgetBuilder itemBuilder;
final int? itemCount;
final ScrollController? controller;
final double maxWidth;
final double maxHeight;
final double width;
final double height;
final ListOverlayFooter? footer;
@override
Widget build(BuildContext context) {
const padding = EdgeInsets.symmetric(horizontal: 6, vertical: 6);
double totalHeight = height + padding.vertical;
if (footer != null) {
totalHeight = totalHeight + footer!.height + footer!.padding.vertical;
}
return Material(
type: MaterialType.transparency,
child: Container(
constraints: BoxConstraints.tight(Size(maxWidth, maxHeight + padding.vertical)),
decoration: FlowyDecoration.decoration(),
constraints: BoxConstraints.tight(Size(width, totalHeight)),
child: Padding(
padding: padding,
child: ListView.builder(
child: Column(
children: [
ListView.builder(
shrinkWrap: true,
itemBuilder: itemBuilder,
itemCount: itemCount,
controller: controller,
),
if (footer != null)
SizedBox(
height: footer!.height,
child: Padding(
padding: footer!.padding,
child: SizedBox.expand(child: footer!.widget),
),
),
],
),
),
),
);
@ -45,27 +75,31 @@ class ListOverlay extends StatelessWidget {
required IndexedWidgetBuilder itemBuilder,
int? itemCount,
ScrollController? controller,
double maxWidth = double.infinity,
double maxHeight = double.infinity,
double width = double.infinity,
double height = double.infinity,
required BuildContext anchorContext,
AnchorDirection? anchorDirection,
FlowyOverlayDelegate? delegate,
OverlapBehaviour? overlapBehaviour,
FlowyOverlayStyle? style,
Offset? anchorOffset,
ListOverlayFooter? footer,
}) {
FlowyOverlay.of(context).insertWithAnchor(
widget: ListOverlay(
itemBuilder: itemBuilder,
itemCount: itemCount,
controller: controller,
maxWidth: maxWidth,
maxHeight: maxHeight,
width: width,
height: height,
footer: footer,
),
identifier: identifier,
anchorContext: anchorContext,
anchorDirection: anchorDirection,
delegate: delegate,
overlapBehaviour: overlapBehaviour,
anchorOffset: anchorOffset,
style: style,
);
}
@ -91,8 +125,8 @@ class ListOverlay extends StatelessWidget {
itemBuilder: itemBuilder,
itemCount: itemCount,
controller: controller,
maxWidth: maxWidth,
maxHeight: maxHeight,
width: maxWidth,
height: maxHeight,
),
identifier: identifier,
anchorPosition: anchorPosition,

View File

@ -22,14 +22,14 @@ class OptionOverlay<T> extends StatelessWidget {
static void showWithAnchor<T>(
BuildContext context, {
required String identifier,
required List<T> items,
required String identifier,
required BuildContext anchorContext,
IndexedValueCallback<T>? onHover,
IndexedValueCallback<T>? onTap,
required BuildContext anchorContext,
AnchorDirection? anchorDirection,
FlowyOverlayDelegate? delegate,
OverlapBehaviour? overlapBehaviour,
FlowyOverlayDelegate? delegate,
}) {
FlowyOverlay.of(context).insertWithAnchor(
widget: OptionOverlay(

View File

@ -65,6 +65,7 @@ class FlowyTextButton extends StatelessWidget {
final Color? fillColor;
final BorderRadius? radius;
final MainAxisAlignment mainAxisAlignment;
final String? tooltip;
// final HoverDisplayConfig? hoverDisplay;
const FlowyTextButton(
@ -80,6 +81,7 @@ class FlowyTextButton extends StatelessWidget {
this.heading,
this.radius,
this.mainAxisAlignment = MainAxisAlignment.start,
this.tooltip,
}) : super(key: key);
@override
@ -108,7 +110,7 @@ class FlowyTextButton extends StatelessWidget {
),
);
return RawMaterialButton(
child = RawMaterialButton(
visualDensity: VisualDensity.compact,
hoverElevation: 0,
highlightElevation: 0,
@ -123,20 +125,14 @@ class FlowyTextButton extends StatelessWidget {
child: child,
);
// if (hoverColor != null) {
// return InkWell(
// onTap: onPressed,
// child: FlowyHover(
// config: HoverDisplayConfig(borderRadius: radius ?? BorderRadius.circular(6), hoverColor: hoverColor!),
// builder: (context, onHover) => child,
// ),
// );
// } else {
// return InkWell(
// onTap: onPressed,
// child: child,
// );
// }
if (tooltip != null) {
child = Tooltip(
message: tooltip!,
child: child,
);
}
return child;
}
}
// return TextButton(

View File

@ -597,6 +597,48 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
package_info_plus:
dependency: "direct main"
description:
name: package_info_plus
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
package_info_plus_linux:
dependency: transitive
description:
name: package_info_plus_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
package_info_plus_macos:
dependency: transitive
description:
name: package_info_plus_macos
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
package_info_plus_web:
dependency: transitive
description:
name: package_info_plus_web
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
package_info_plus_windows:
dependency: transitive
description:
name: package_info_plus_windows
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
path:
dependency: transitive
description:

View File

@ -63,6 +63,7 @@ dependencies:
expandable: ^5.0.1
flutter_svg: ^0.22.0
flutter_colorpicker: ^0.6.0
package_info_plus: ^1.3.0
# The following adds the Cupertino Icons font to your application.