Add Lottie image support

This commit updates a variety of dependencies including 'archive', 'lottie', and several 'syncfusion' packages. It also introduces support for Lottie animations in Wox.Image. This includes adding a Lottie enumeration to several files, creating helper functions related to Lottie in WoxImage, and handling Lottie input in ImageView.
This commit is contained in:
qianlifeng 2024-07-07 23:10:35 +08:00
parent 213671919a
commit fcaa1be824
No known key found for this signature in database
10 changed files with 79 additions and 37 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@wox-launcher/wox-plugin", "name": "@wox-launcher/wox-plugin",
"version": "0.0.72", "version": "0.0.74",
"description": "All nodejs plugin for Wox should use types in this package", "description": "All nodejs plugin for Wox should use types in this package",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -98,8 +98,8 @@ export interface Result {
export interface ResultTail { export interface ResultTail {
Type: "text" | "image" Type: "text" | "image"
Text: string Text?: string
Image: WoxImage Image?: WoxImage
} }
export interface RefreshableResult { export interface RefreshableResult {
@ -216,7 +216,7 @@ export interface PublicAPI {
LLMStream: (ctx: Context, conversations: AI.Conversation[], callback: AI.ChatStreamFunc) => Promise<void> LLMStream: (ctx: Context, conversations: AI.Conversation[], callback: AI.ChatStreamFunc) => Promise<void>
} }
export type WoxImageType = "absolute" | "relative" | "base64" | "svg" | "url" | "emoji" export type WoxImageType = "absolute" | "relative" | "base64" | "svg" | "url" | "emoji" | "lottie"
export interface WoxImage { export interface WoxImage {
ImageType: WoxImageType ImageType: WoxImageType

View File

@ -3,6 +3,7 @@ import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:lottie/lottie.dart';
import 'package:wox/entity/wox_image.dart'; import 'package:wox/entity/wox_image.dart';
import 'package:wox/enums/wox_image_type_enum.dart'; import 'package:wox/enums/wox_image_type_enum.dart';
@ -31,6 +32,9 @@ class WoxImageView extends StatelessWidget {
return SvgPicture.string(woxImage.imageData, width: width, height: height); return SvgPicture.string(woxImage.imageData, width: width, height: height);
} else if (woxImage.imageType == WoxImageTypeEnum.WOX_IMAGE_TYPE_EMOJI.code) { } else if (woxImage.imageType == WoxImageTypeEnum.WOX_IMAGE_TYPE_EMOJI.code) {
return Text(woxImage.imageData, style: TextStyle(fontSize: width)); return Text(woxImage.imageData, style: TextStyle(fontSize: width));
} else if (woxImage.imageType == WoxImageTypeEnum.WOX_IMAGE_TYPE_LOTTIE.code) {
final bytes = utf8.encode(woxImage.imageData);
return Lottie.memory(bytes, width: width, height: height);
} else if (woxImage.imageType == WoxImageTypeEnum.WOX_IMAGE_TYPE_BASE64.code) { } else if (woxImage.imageType == WoxImageTypeEnum.WOX_IMAGE_TYPE_BASE64.code) {
if (!woxImage.imageData.contains(";base64,")) { if (!woxImage.imageData.contains(";base64,")) {
return Text("Invalid image data: ${woxImage.imageData}", style: const TextStyle(color: Colors.red)); return Text("Invalid image data: ${woxImage.imageData}", style: const TextStyle(color: Colors.red));

View File

@ -6,6 +6,7 @@ import 'package:wox/components/wox_image_view.dart';
import 'package:wox/entity/wox_image.dart'; import 'package:wox/entity/wox_image.dart';
import 'package:wox/entity/wox_query.dart'; import 'package:wox/entity/wox_query.dart';
import 'package:wox/entity/wox_theme.dart'; import 'package:wox/entity/wox_theme.dart';
import 'package:wox/enums/wox_image_type_enum.dart';
import 'package:wox/enums/wox_list_view_type_enum.dart'; import 'package:wox/enums/wox_list_view_type_enum.dart';
import 'package:wox/enums/wox_result_tail_type_enum.dart'; import 'package:wox/enums/wox_result_tail_type_enum.dart';
import 'package:wox/utils/log.dart'; import 'package:wox/utils/log.dart';
@ -37,6 +38,14 @@ class WoxListItemView extends StatelessWidget {
return listViewType == WoxListViewTypeEnum.WOX_LIST_VIEW_TYPE_ACTION.code; return listViewType == WoxListViewTypeEnum.WOX_LIST_VIEW_TYPE_ACTION.code;
} }
double getImageSize(WoxImage img, double defaultSize) {
if (img.imageType == WoxImageTypeEnum.WOX_IMAGE_TYPE_EMOJI.code) {
return defaultSize - 10;
} else {
return defaultSize;
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (LoggerSwitch.enablePaintLog) Logger.instance.info(const UuidV4().generate(), "repaint: list item view $key - container"); if (LoggerSwitch.enablePaintLog) Logger.instance.info(const UuidV4().generate(), "repaint: list item view $key - container");
@ -72,8 +81,8 @@ class WoxListItemView extends StatelessWidget {
return WoxImageView( return WoxImageView(
woxImage: icon.value, woxImage: icon.value,
width: 30, width: getImageSize(icon.value, 30),
height: 30, height: getImageSize(icon.value, 30),
); );
})), })),
Expanded( Expanded(
@ -140,7 +149,7 @@ class WoxListItemView extends StatelessWidget {
tail.text, tail.text,
style: TextStyle( style: TextStyle(
color: fromCssColor(isActive ? woxTheme.resultItemActiveTailTextColor : woxTheme.resultItemTailTextColor), color: fromCssColor(isActive ? woxTheme.resultItemActiveTailTextColor : woxTheme.resultItemTailTextColor),
fontSize: 13, fontSize: 12,
), ),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@ -154,8 +163,8 @@ class WoxListItemView extends StatelessWidget {
padding: const EdgeInsets.only(left: 10.0), padding: const EdgeInsets.only(left: 10.0),
child: WoxImageView( child: WoxImageView(
woxImage: tail.image, woxImage: tail.image,
width: 14, width: getImageSize(tail.image, 24),
height: 14, height: getImageSize(tail.image, 24),
), ),
), ),
], ],

View File

@ -5,6 +5,7 @@ enum WoxImageTypeEnum {
WOX_IMAGE_TYPE_RELATIVE_PATH("relative", "relative"), WOX_IMAGE_TYPE_RELATIVE_PATH("relative", "relative"),
WOX_IMAGE_TYPE_BASE64("base64", "base64"), WOX_IMAGE_TYPE_BASE64("base64", "base64"),
WOX_IMAGE_TYPE_SVG("svg", "svg"), WOX_IMAGE_TYPE_SVG("svg", "svg"),
WOX_IMAGE_TYPE_LOTTIE("lottie", "lottie"),
WOX_IMAGE_TYPE_EMOJI("emoji", "emoji"), WOX_IMAGE_TYPE_EMOJI("emoji", "emoji"),
WOX_IMAGE_TYPE_URL("url", "url"); WOX_IMAGE_TYPE_URL("url", "url");

View File

@ -1,6 +1,14 @@
# Generated by pub # Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile # See https://dart.dev/tools/pub/glossary#lockfile
packages: packages:
archive:
dependency: transitive
description:
name: archive
sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
url: "https://pub.dev"
source: hosted
version: "3.6.1"
args: args:
dependency: transitive dependency: transitive
description: description:
@ -437,6 +445,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.3.0"
lottie:
dependency: "direct main"
description:
name: lottie
sha256: "6a24ade5d3d918c306bb1c21a6b9a04aab0489d51a2582522eea820b4093b62b"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
lpinyin: lpinyin:
dependency: "direct main" dependency: "direct main"
description: description:
@ -718,66 +734,66 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: syncfusion_flutter_core name: syncfusion_flutter_core
sha256: "2cd3a1c59bd9c2863eee96cc5400429ecc7b42cd1e7379f3eb5ccd9fc2e9306b" sha256: "87cbeee9b916e013eedbd43bf07f253c34dd5184c88325e5227434e0f8b89a68"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "26.1.38" version: "26.1.40"
syncfusion_flutter_pdf: syncfusion_flutter_pdf:
dependency: transitive dependency: transitive
description: description:
name: syncfusion_flutter_pdf name: syncfusion_flutter_pdf
sha256: "6412b286e2946f4865d835500fe08293a171f6e3d0907843088fb66e7d004cd9" sha256: d664fc067cf564cad4f1dd56ec960efb7e9d3191d14959f3228e4d3e195397e4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "26.1.38" version: "26.1.40"
syncfusion_flutter_pdfviewer: syncfusion_flutter_pdfviewer:
dependency: "direct main" dependency: "direct main"
description: description:
name: syncfusion_flutter_pdfviewer name: syncfusion_flutter_pdfviewer
sha256: b8defa316c13cef9f1964b0dd166d25d868179f4470916c66310f62421c2d7bc sha256: "31762e18da82dd862022756ae1601605b9d9d9806565f848029aeb2aa9843e01"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "26.1.38" version: "26.1.40"
syncfusion_flutter_signaturepad: syncfusion_flutter_signaturepad:
dependency: transitive dependency: transitive
description: description:
name: syncfusion_flutter_signaturepad name: syncfusion_flutter_signaturepad
sha256: "3abeda28f047ea1d7c11028a5d198d5b0dbd056fbbd7e6bef44c65e47a29c1b3" sha256: "9ace56fa99a99d3565917225434bd372ea20fec9715288ba7829d0ab356ded69"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "26.1.38" version: "26.1.40"
syncfusion_pdfviewer_macos: syncfusion_pdfviewer_macos:
dependency: transitive dependency: transitive
description: description:
name: syncfusion_pdfviewer_macos name: syncfusion_pdfviewer_macos
sha256: d3b168dbdcc9570b95893a792f7d89947c8e7f24db78d2bb38158ba45ac56e14 sha256: "3f9d6455a63ba53e1650985b199eb7091900e930d2514259185c57be0645a147"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "26.1.38" version: "26.1.40"
syncfusion_pdfviewer_platform_interface: syncfusion_pdfviewer_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: syncfusion_pdfviewer_platform_interface name: syncfusion_pdfviewer_platform_interface
sha256: "513651b004ae6f1d1d23dab27febd1b3b73fc6465c59b8bfec263af91498fbe6" sha256: "63d538940e359e248ae62f18814d96f9972bc048c51b37975c218391f0ec61de"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "26.1.38" version: "26.1.40"
syncfusion_pdfviewer_web: syncfusion_pdfviewer_web:
dependency: transitive dependency: transitive
description: description:
name: syncfusion_pdfviewer_web name: syncfusion_pdfviewer_web
sha256: "2f79038277bf086b3d811f3a0577f2412ce2d2744bda3bc2da9dc69719e747c1" sha256: "8c6666a9dc7beeb30c9dd8a5cbb7933f4b79219320f3bb358f00a5f3e2f8de68"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "26.1.38" version: "26.1.40"
syncfusion_pdfviewer_windows: syncfusion_pdfviewer_windows:
dependency: transitive dependency: transitive
description: description:
name: syncfusion_pdfviewer_windows name: syncfusion_pdfviewer_windows
sha256: "0318bb500daedf060f4bb182da6d01fb3f0ef13dc427219fae1e2862ebbeffbb" sha256: dc310506dc364c403575ac59c5a2127f1e6a72cde695cf236ce31ac0058b8fb0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "26.1.38" version: "26.1.40"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:

View File

@ -60,6 +60,7 @@ dependencies:
flutter_code_editor: ^0.3.1 flutter_code_editor: ^0.3.1
flutter_highlight: ^0.7.0 flutter_highlight: ^0.7.0
highlight: ^0.7.0 highlight: ^0.7.0
lottie: ^3.1.2
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View File

@ -29,6 +29,7 @@ const (
WoxImageTypeRelativePath = "relative" WoxImageTypeRelativePath = "relative"
WoxImageTypeBase64 = "base64" WoxImageTypeBase64 = "base64"
WoxImageTypeSvg = "svg" WoxImageTypeSvg = "svg"
WoxImageTypeLottie = "lottie" // only support lottie json data
WoxImageTypeEmoji = "emoji" WoxImageTypeEmoji = "emoji"
WoxImageTypeUrl = "url" WoxImageTypeUrl = "url"
) )
@ -190,6 +191,10 @@ func (w *WoxImage) OverlayFullPercentage(overlay WoxImage, percentage float64) W
return overlayWoxImg return overlayWoxImg
} }
func (w *WoxImage) IsGif() bool {
return strings.HasSuffix(w.ImageData, ".gif")
}
func NewWoxImageSvg(svg string) WoxImage { func NewWoxImageSvg(svg string) WoxImage {
return WoxImage{ return WoxImage{
ImageType: WoxImageTypeSvg, ImageType: WoxImageTypeSvg,
@ -235,6 +240,13 @@ func NewWoxImageEmoji(emoji string) WoxImage {
} }
} }
func NewWoxImageLottie(lottieJson string) WoxImage {
return WoxImage{
ImageType: WoxImageTypeLottie,
ImageData: lottieJson,
}
}
func ParseWoxImageOrDefault(image string, defaultImage WoxImage) WoxImage { func ParseWoxImageOrDefault(image string, defaultImage WoxImage) WoxImage {
if image == "" { if image == "" {
return defaultImage return defaultImage
@ -295,6 +307,9 @@ func resizeImage(ctx context.Context, image WoxImage, size int) (newImage WoxIma
if image.ImageType == WoxImageTypeEmoji { if image.ImageType == WoxImageTypeEmoji {
return image return image
} }
if image.IsGif() {
return image
}
newImage = image newImage = image
@ -336,6 +351,9 @@ func cropPngTransparentPaddings(ctx context.Context, woxImage WoxImage) (newImag
if woxImage.ImageType == WoxImageTypeEmoji { if woxImage.ImageType == WoxImageTypeEmoji {
return woxImage return woxImage
} }
if woxImage.IsGif() {
return woxImage
}
//try load from cache first //try load from cache first
imgHash := woxImage.Hash() imgHash := woxImage.Hash()

View File

@ -456,6 +456,11 @@ func (m *Manager) PolishResult(ctx context.Context, pluginInstance *Instance, qu
// convert icon // convert icon
result.Icon = ConvertIcon(ctx, result.Icon, pluginInstance.PluginDirectory) result.Icon = ConvertIcon(ctx, result.Icon, pluginInstance.PluginDirectory)
for i := range result.Tails {
if result.Tails[i].Type == QueryResultTailTypeImage {
result.Tails[i].Image = ConvertIcon(ctx, result.Tails[i].Image, pluginInstance.PluginDirectory)
}
}
// add default preview for selection query if no preview is set // add default preview for selection query if no preview is set
if query.Type == QueryTypeSelection && result.Preview.PreviewType == "" { if query.Type == QueryTypeSelection && result.Preview.PreviewType == "" {

View File

@ -147,13 +147,6 @@ func (a *ApplicationPlugin) Query(ctx context.Context, query plugin.Query) []plu
Icon: info.Icon, Icon: info.Icon,
Tails: tails, Tails: tails,
Score: util.MaxInt64(nameScore, pathNameScore), Score: util.MaxInt64(nameScore, pathNameScore),
Preview: plugin.WoxPreview{
PreviewType: plugin.WoxPreviewTypeText,
PreviewData: info.Path,
PreviewProperties: map[string]string{
"Path": info.Path,
},
},
Actions: []plugin.QueryResultAction{ Actions: []plugin.QueryResultAction{
{ {
Name: "i18n:plugin_app_open", Name: "i18n:plugin_app_open",
@ -250,11 +243,6 @@ func (a *ApplicationPlugin) getRunningProcessResult(pid int) (tails []plugin.Que
Text: fmt.Sprintf("Mem: %.1f %s", memSize, unit), Text: fmt.Sprintf("Mem: %.1f %s", memSize, unit),
}) })
tails = append(tails, plugin.QueryResultTail{
Type: plugin.QueryResultTailTypeImage,
Image: plugin.NewWoxImageEmoji(`🖥️`),
})
return return
} }