Add an animated AI icon for Scribe in desktop web
I moved the previous static icon in its own component and created a component that manage the loading of the appropriate icon: static or dynamic.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -247,6 +247,7 @@ class ImagePaths {
|
||||
String get icFileDownload => _getImagePath('ic_file_download.svg');
|
||||
String get icTwakeWorkplace => _getIconPath('icon_twp.png');
|
||||
String get animLottieTmail => _getAnimationPath('lottie-tmail.json');
|
||||
String get animLottieScribe => _getAnimationPath('lottie-scribe.json');
|
||||
String get icExpandArrows => _getImagePath('ic_expand_arrows.svg');
|
||||
String get icPremium => _getImagePath('ic_premium.svg');
|
||||
String get icCloud => _getImagePath('ic_cloud.svg');
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/views/container/tmail_container_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
import 'package:scribe/scribe.dart';
|
||||
|
||||
class AiAssistantAnimatedButton extends StatefulWidget {
|
||||
final ImagePaths imagePaths;
|
||||
final void Function() onTapActionCallback;
|
||||
final EdgeInsetsGeometry? margin;
|
||||
|
||||
const AiAssistantAnimatedButton({
|
||||
super.key,
|
||||
required this.imagePaths,
|
||||
required this.onTapActionCallback,
|
||||
this.margin,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AiAssistantAnimatedButton> createState() =>
|
||||
_AiAssistantAnimatedButtonState();
|
||||
}
|
||||
|
||||
class _AiAssistantAnimatedButtonState extends State<AiAssistantAnimatedButton>
|
||||
with TickerProviderStateMixin {
|
||||
late AnimationController _animationController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_animationController = AnimationController(vsync: this);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_animationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TMailContainerWidget(
|
||||
margin: widget.margin,
|
||||
padding: AIScribeSizes.aiAssistantIconPadding,
|
||||
backgroundColor: Colors.transparent,
|
||||
borderRadius: AIScribeSizes.aiAssistantIconRadius,
|
||||
tooltipMessage: ScribeLocalizations.of(context).aiAssistant,
|
||||
onTapActionCallback: widget.onTapActionCallback,
|
||||
child: MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (event) {
|
||||
_animationController.forward();
|
||||
},
|
||||
onExit: (event) {
|
||||
_animationController.reset();
|
||||
},
|
||||
child: Lottie.asset(
|
||||
widget.imagePaths.animLottieScribe,
|
||||
width: AIScribeSizes.aiAssistantIcon,
|
||||
height: AIScribeSizes.aiAssistantIcon,
|
||||
fit: BoxFit.fill,
|
||||
controller: _animationController,
|
||||
onLoaded: (composition) {
|
||||
_animationController.duration = composition.duration;
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:scribe/scribe.dart';
|
||||
import 'ai_assistant_animated_button.dart';
|
||||
import 'ai_assistant_static_button.dart';
|
||||
|
||||
typedef OnOpenAiAssistantModal = void Function(
|
||||
Offset? position,
|
||||
@@ -24,18 +25,21 @@ class AiAssistantButton extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TMailButtonWidget.fromIcon(
|
||||
icon: imagePaths.icGradientSparkle,
|
||||
padding: AIScribeSizes.aiAssistantIconPadding,
|
||||
backgroundColor: Colors.transparent,
|
||||
iconSize: AIScribeSizes.aiAssistantIcon,
|
||||
if (PlatformInfo.isWebDesktop) {
|
||||
return AiAssistantAnimatedButton(
|
||||
imagePaths: imagePaths,
|
||||
onTapActionCallback: () => _onTapActionCallback(context),
|
||||
margin: margin,
|
||||
);
|
||||
} else {
|
||||
return AiAssistantStaticButton(
|
||||
imagePaths: imagePaths,
|
||||
onTapActionCallback: () => _onTapActionCallback(context),
|
||||
iconColor: iconColor,
|
||||
margin: margin,
|
||||
borderRadius: AIScribeSizes.aiAssistantIconRadius,
|
||||
tooltipMessage: ScribeLocalizations.of(context).aiAssistant,
|
||||
onTapActionCallback: () => _onTapActionCallback(context),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _onTapActionCallback(BuildContext context) {
|
||||
final renderBox = context.findRenderObject();
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import 'package:core/presentation/resources/image_paths.dart';
|
||||
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:scribe/scribe.dart';
|
||||
|
||||
class AiAssistantStaticButton extends StatelessWidget {
|
||||
final ImagePaths imagePaths;
|
||||
final void Function() onTapActionCallback;
|
||||
final Color? iconColor;
|
||||
final EdgeInsetsGeometry? margin;
|
||||
|
||||
const AiAssistantStaticButton({
|
||||
super.key,
|
||||
required this.imagePaths,
|
||||
required this.onTapActionCallback,
|
||||
this.iconColor,
|
||||
this.margin,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TMailButtonWidget.fromIcon(
|
||||
icon: imagePaths.icGradientSparkle,
|
||||
padding: AIScribeSizes.aiAssistantIconPadding,
|
||||
backgroundColor: Colors.transparent,
|
||||
iconSize: AIScribeSizes.aiAssistantIcon,
|
||||
iconColor: iconColor,
|
||||
margin: margin,
|
||||
borderRadius: AIScribeSizes.aiAssistantIconRadius,
|
||||
tooltipMessage: ScribeLocalizations.of(context).aiAssistant,
|
||||
onTapActionCallback: onTapActionCallback,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user