Skip to content

Commit c7efa9b

Browse files
adding the animated image widget 🔥 (#41)
* using babel plugin in eslint 🛠 * adding eslint babel plugin 📦 * adding util to get contents for animated image 🔥 * creating the animated image component 🔥 * adding docs for animated image 📚
1 parent 797802c commit c7efa9b

File tree

15 files changed

+739
-4
lines changed

15 files changed

+739
-4
lines changed

.eslintrc.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ module.exports = {
55
},
66
"parser": "@typescript-eslint/parser",
77
"plugins": [
8-
"@typescript-eslint"
8+
"@typescript-eslint",
9+
"babel"
910
],
1011
"extends": [
1112
"airbnb-base",
@@ -53,6 +54,8 @@ module.exports = {
5354
],
5455
"class-methods-use-this": 0,
5556
"max-classes-per-file": 0,
56-
'import/no-cycle': 0
57+
'import/no-cycle': 0,
58+
"no-unused-expressions": 0,
59+
"babel/no-unused-expressions": "error"
5760
}
5861
}

package-lock.json

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"eslint-config-airbnb-base": "^14.2.0",
4646
"eslint-config-prettier": "^6.11.0",
4747
"eslint-import-resolver-typescript": "^2.3.0",
48+
"eslint-plugin-babel": "^5.3.1",
4849
"eslint-plugin-import": "^2.21.2",
4950
"file-loader": "^5.0.2",
5051
"husky": "^4.3.0",

src/utils/image.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { QPixmap } from '@nodegui/nodegui';
1+
import { QMovie, QPixmap } from '@nodegui/nodegui';
22
import phin from 'phin';
33
import { isValidUrl } from './url';
44

@@ -13,3 +13,15 @@ export async function getLoadedPixmap(imageUrlOrPath: string): Promise<QPixmap>
1313
}
1414
return pixMap;
1515
}
16+
17+
export async function getLoadedQMovie(imageUrlOrPath: string): Promise<QMovie> {
18+
const movie = new QMovie();
19+
if (isValidUrl(imageUrlOrPath)) {
20+
const res = await phin(imageUrlOrPath);
21+
const imageBuffer = Buffer.from(res.body);
22+
movie.loadFromData(imageBuffer);
23+
} else {
24+
movie.setFileName(imageUrlOrPath);
25+
}
26+
return movie;
27+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { QLabel, NodeWidget, QMovie } from '@nodegui/nodegui';
2+
import { getLoadedQMovie } from '../../utils/image';
3+
import { Prop, PropSetters } from '../../renderer/patchProp';
4+
import { TextProps, textPropsSetters } from '../Text/VNText';
5+
import { VNWidget } from '../config';
6+
7+
/**
8+
* The animated image widget allows users to create and render native GIFs, video (without controls)
9+
* elements in the app.
10+
* It is based on [NodeGui's QLabel](https://docs.nodegui.org/docs/api/generated/classes/qlabel) along with [NodeGui's QMovie](https://docs.nodegui.org/docs/api/generated/classes/qmovie)
11+
*
12+
* ## Usage
13+
*
14+
* ```html
15+
* <template>
16+
* <vn-view>
17+
* <vn-animated-image :src="'https://i.giphy.com/media/oYtVHSxngR3lC/giphy.gif'" />
18+
* </vn-view>
19+
* </template>
20+
*
21+
* <script>
22+
* export default { }
23+
* </script>
24+
* ```
25+
*
26+
* ## What it looks like?
27+
*
28+
* ![animated-image-demo](/img/vn-animated-image.gif)
29+
*
30+
* ## Props and styling
31+
*
32+
* You can find all the props `vn-animated-image` accepts listed below.
33+
* Apart from this, you can take a look at the [styling](/docs/guides/3-styling)
34+
* and [event handling](/docs/guides/5-handle-events) docs
35+
*/
36+
export interface AnimatedImageProps extends TextProps {
37+
src?: string;
38+
buffer?: Buffer;
39+
}
40+
41+
export const animatedImagePropsSetters: PropSetters<VNAnimatedImage, AnimatedImageProps> = {
42+
...textPropsSetters,
43+
src: (widget: VNAnimatedImage, _, nextValue: string) => {
44+
if (!nextValue) {
45+
return;
46+
}
47+
getLoadedQMovie(nextValue)
48+
.then((movie) => {
49+
widget.setMovie(movie);
50+
widget.movie()?.start();
51+
})
52+
.catch(console.warn);
53+
},
54+
buffer: (widget: VNAnimatedImage, _, nextValue: Buffer) => {
55+
const movie = new QMovie();
56+
movie.loadFromData(nextValue);
57+
widget.setMovie(movie);
58+
widget.movie()?.start();
59+
},
60+
};
61+
62+
/** @internal */
63+
export class VNAnimatedImage extends QLabel implements VNWidget<AnimatedImageProps> {
64+
insertChild() {
65+
throw new Error('Cannot add child to animated image elements');
66+
}
67+
68+
patchProp(
69+
key: keyof AnimatedImageProps,
70+
prevValue: Prop<AnimatedImageProps, typeof key>,
71+
nextValue: Prop<AnimatedImageProps, typeof key>,
72+
) {
73+
const propSetter = animatedImagePropsSetters[key];
74+
if (propSetter !== undefined) { propSetter(this, prevValue as never, nextValue as never); }
75+
}
76+
77+
removeChild() {
78+
throw new Error('Cannot remove/add child to animated image elements');
79+
}
80+
81+
insertBefore() {
82+
throw new Error('Cannot add child to animated image elements');
83+
}
84+
85+
getNextSibling(): NodeWidget<any> | null {
86+
throw new Error('animated image cannot have children');
87+
}
88+
}

src/widgets/AnimatedImage/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { VNAnimatedImage, AnimatedImageProps } from './VNAnimatedImage';
2+
import { WidgetConfig } from '../config';
3+
4+
class AnimatedImageConfig implements WidgetConfig<AnimatedImageProps> {
5+
parentNode: any;
6+
7+
createElement() {
8+
return new VNAnimatedImage();
9+
}
10+
}
11+
12+
export default AnimatedImageConfig;

src/widgets/nativeWidget.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ export type ValidNativeWidgets = 'vn-image' |
1010
'vn-spinbox' |
1111
'vn-progress-bar' |
1212
'vn-combobox' |
13-
'vn-dial';
13+
'vn-dial' |
14+
'vn-animated-image';
1415

1516
// Add vue-nodegui widgets here
1617
// whenever new ones are created
@@ -28,6 +29,7 @@ const nativeWidgets: {[key in ValidNativeWidgets]: boolean} = {
2829
'vn-progress-bar': true,
2930
'vn-combobox': true,
3031
'vn-dial': true,
32+
'vn-animated-image': true,
3133
};
3234

3335
export const isNativeWidget = (type: ValidNativeWidgets) => !!nativeWidgets[type];

src/widgets/widgetMap.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import SpinBoxConfig from './SpinBox';
1111
import ProgressBarConfig from './ProgressBar';
1212
import ComboBoxConfig from './ComboBox';
1313
import DialConfig from './Dial';
14+
import AnimatedImageConfig from './AnimatedImage';
1415
import { ValidNativeWidgets } from './nativeWidget';
1516
import { WidgetConfig } from './config';
1617

@@ -32,6 +33,7 @@ const widgetMap: WidgetMap = {
3233
'vn-progress-bar': new ProgressBarConfig(),
3334
'vn-combobox': new ComboBoxConfig(),
3435
'vn-dial': new DialConfig(),
36+
'vn-animated-image': new AnimatedImageConfig(),
3537
};
3638

3739
const getConfigByType = (type: ValidNativeWidgets) => {
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
---
2+
id: "animatedimageprops"
3+
title: "AnimatedImageProps"
4+
sidebar_label: "AnimatedImageProps"
5+
---
6+
7+
The animated image widget allows users to create and render native GIFs, video (without controls)
8+
elements in the app.
9+
It is based on [NodeGui's QLabel](https://docs.nodegui.org/docs/api/generated/classes/qlabel) along with [NodeGui's QMovie](https://docs.nodegui.org/docs/api/generated/classes/qmovie)
10+
11+
## Usage
12+
13+
```html
14+
<template>
15+
<vn-view>
16+
<vn-animated-image :src="'https://i.giphy.com/media/oYtVHSxngR3lC/giphy.gif'" />
17+
</vn-view>
18+
</template>
19+
20+
<script>
21+
export default { }
22+
</script>
23+
```
24+
25+
## What it looks like?
26+
27+
![animated-image-demo](/img/vn-animated-image.gif)
28+
29+
## Props and styling
30+
31+
You can find all the props `vn-animated-image` accepts listed below.
32+
Apart from this, you can take a look at the [styling](/docs/guides/3-styling)
33+
and [event handling](/docs/guides/5-handle-events) docs
34+
35+
## Hierarchy
36+
37+
[TextProps](textprops.md)
38+
39+
**AnimatedImageProps**
40+
41+
## Index
42+
43+
### Properties
44+
45+
* [buffer](animatedimageprops.md#optional-buffer)
46+
* [enabled](animatedimageprops.md#optional-enabled)
47+
* [id](animatedimageprops.md#optional-id)
48+
* [mouseTracking](animatedimageprops.md#optional-mousetracking)
49+
* [openExternalLinks](animatedimageprops.md#optional-openexternallinks)
50+
* [scaledContents](animatedimageprops.md#optional-scaledcontents)
51+
* [src](animatedimageprops.md#optional-src)
52+
* [style](animatedimageprops.md#optional-style)
53+
* [styleSheet](animatedimageprops.md#optional-stylesheet)
54+
* [visible](animatedimageprops.md#optional-visible)
55+
* [windowOpacity](animatedimageprops.md#optional-windowopacity)
56+
* [windowTitle](animatedimageprops.md#optional-windowtitle)
57+
* [wordWrap](animatedimageprops.md#optional-wordwrap)
58+
59+
## Properties
60+
61+
### `Optional` buffer
62+
63+
**buffer**? : *Buffer*
64+
65+
___
66+
67+
### `Optional` enabled
68+
69+
**enabled**? : *undefined | false | true*
70+
71+
*Inherited from [ViewProps](viewprops.md).[enabled](viewprops.md#optional-enabled)*
72+
73+
Sets the property that tells whether the widget is enabled. In general an enabled widget handles keyboard and mouse events; a disabled widget does not. [QWidget: setEnabled](https://docs.nodegui.org/docs/api/NodeWidget#widgetsetenabledenabled)
74+
75+
___
76+
77+
### `Optional` id
78+
79+
**id**? : *undefined | string*
80+
81+
*Inherited from [ViewProps](viewprops.md).[id](viewprops.md#optional-id)*
82+
83+
Sets the object name (id) of the widget in Qt. Object name can be analogous to id of an element in the web world. Using the objectName of the widget one can reference it in the Qt's stylesheet much like what we do with id in the web world. [QWidget: setObjectName](https://docs.nodegui.org/docs/api/NodeWidget#widgetsetobjectnameobjectname)
84+
85+
___
86+
87+
### `Optional` mouseTracking
88+
89+
**mouseTracking**? : *undefined | false | true*
90+
91+
*Inherited from [ViewProps](viewprops.md).[mouseTracking](viewprops.md#optional-mousetracking)*
92+
93+
Sets the property that tells whether mouseTracking is enabled for the widget. [QWidget: setMouseTracking](https://docs.nodegui.org/docs/api/NodeWidget#widgetsetmousetrackingismousetracked)
94+
95+
___
96+
97+
### `Optional` openExternalLinks
98+
99+
**openExternalLinks**? : *undefined | false | true*
100+
101+
*Inherited from [TextProps](textprops.md).[openExternalLinks](textprops.md#optional-openexternallinks)*
102+
103+
___
104+
105+
### `Optional` scaledContents
106+
107+
**scaledContents**? : *undefined | false | true*
108+
109+
*Inherited from [TextProps](textprops.md).[scaledContents](textprops.md#optional-scaledcontents)*
110+
111+
___
112+
113+
### `Optional` src
114+
115+
**src**? : *undefined | string*
116+
117+
___
118+
119+
### `Optional` style
120+
121+
**style**? : *undefined | string*
122+
123+
*Inherited from [ViewProps](viewprops.md).[style](viewprops.md#optional-style)*
124+
125+
Sets the inline stylesheet property. [QWidget: setInlineStyle](https://docs.nodegui.org/docs/api/NodeWidget#widgetsetinlinestylestyle)
126+
127+
___
128+
129+
### `Optional` styleSheet
130+
131+
**styleSheet**? : *undefined | string*
132+
133+
*Inherited from [ViewProps](viewprops.md).[styleSheet](viewprops.md#optional-stylesheet)*
134+
135+
Sets the property that holds the widget's style sheet. [QWidget: setStyleSheet](https://docs.nodegui.org/docs/api/NodeWidget#widgetsetstylesheetstylesheet)
136+
137+
___
138+
139+
### `Optional` visible
140+
141+
**visible**? : *undefined | false | true*
142+
143+
*Inherited from [ViewProps](viewprops.md).[visible](viewprops.md#optional-visible)*
144+
145+
Shows or hides the widget and its children. [QWidget: show](https://docs.nodegui.org/docs/api/NodeWidget#widgetshow)
146+
147+
___
148+
149+
### `Optional` windowOpacity
150+
151+
**windowOpacity**? : *undefined | number*
152+
153+
*Inherited from [ViewProps](viewprops.md).[windowOpacity](viewprops.md#optional-windowopacity)*
154+
155+
This property holds the level of opacity for the window. [QWidget: setWindowOpacity](https://docs.nodegui.org/docs/api/NodeWidget#widgetsetwindowopacityopacity)
156+
157+
___
158+
159+
### `Optional` windowTitle
160+
161+
**windowTitle**? : *undefined | string*
162+
163+
*Inherited from [ViewProps](viewprops.md).[windowTitle](viewprops.md#optional-windowtitle)*
164+
165+
Sets the window title property. [QWidget: setWindowTitle](https://docs.nodegui.org/docs/api/NodeWidget#widgetsetwindowtitletitle)
166+
167+
___
168+
169+
### `Optional` wordWrap
170+
171+
**wordWrap**? : *undefined | false | true*
172+
173+
*Inherited from [TextProps](textprops.md).[wordWrap](textprops.md#optional-wordwrap)*

0 commit comments

Comments
 (0)