Skip to content

adding the animated image widget 🔥 #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ module.exports = {
},
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
"@typescript-eslint",
"babel"
],
"extends": [
"airbnb-base",
Expand Down Expand Up @@ -53,6 +54,8 @@ module.exports = {
],
"class-methods-use-this": 0,
"max-classes-per-file": 0,
'import/no-cycle': 0
'import/no-cycle': 0,
"no-unused-expressions": 0,
"babel/no-unused-expressions": "error"
}
}
15 changes: 15 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"eslint-config-airbnb-base": "^14.2.0",
"eslint-config-prettier": "^6.11.0",
"eslint-import-resolver-typescript": "^2.3.0",
"eslint-plugin-babel": "^5.3.1",
"eslint-plugin-import": "^2.21.2",
"file-loader": "^5.0.2",
"husky": "^4.3.0",
Expand Down
14 changes: 13 additions & 1 deletion src/utils/image.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { QPixmap } from '@nodegui/nodegui';
import { QMovie, QPixmap } from '@nodegui/nodegui';
import phin from 'phin';
import { isValidUrl } from './url';

Expand All @@ -13,3 +13,15 @@ export async function getLoadedPixmap(imageUrlOrPath: string): Promise<QPixmap>
}
return pixMap;
}

export async function getLoadedQMovie(imageUrlOrPath: string): Promise<QMovie> {
const movie = new QMovie();
if (isValidUrl(imageUrlOrPath)) {
const res = await phin(imageUrlOrPath);
const imageBuffer = Buffer.from(res.body);
movie.loadFromData(imageBuffer);
} else {
movie.setFileName(imageUrlOrPath);
}
return movie;
}
88 changes: 88 additions & 0 deletions src/widgets/AnimatedImage/VNAnimatedImage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { QLabel, NodeWidget, QMovie } from '@nodegui/nodegui';
import { getLoadedQMovie } from '../../utils/image';
import { Prop, PropSetters } from '../../renderer/patchProp';
import { TextProps, textPropsSetters } from '../Text/VNText';
import { VNWidget } from '../config';

/**
* The animated image widget allows users to create and render native GIFs, video (without controls)
* elements in the app.
* 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)
*
* ## Usage
*
* ```html
* <template>
* <vn-view>
* <vn-animated-image :src="'https://i.giphy.com/media/oYtVHSxngR3lC/giphy.gif'" />
* </vn-view>
* </template>
*
* <script>
* export default { }
* </script>
* ```
*
* ## What it looks like?
*
* ![animated-image-demo](/img/vn-animated-image.gif)
*
* ## Props and styling
*
* You can find all the props `vn-animated-image` accepts listed below.
* Apart from this, you can take a look at the [styling](/docs/guides/3-styling)
* and [event handling](/docs/guides/5-handle-events) docs
*/
export interface AnimatedImageProps extends TextProps {
src?: string;
buffer?: Buffer;
}

export const animatedImagePropsSetters: PropSetters<VNAnimatedImage, AnimatedImageProps> = {
...textPropsSetters,
src: (widget: VNAnimatedImage, _, nextValue: string) => {
if (!nextValue) {
return;
}
getLoadedQMovie(nextValue)
.then((movie) => {
widget.setMovie(movie);
widget.movie()?.start();
})
.catch(console.warn);
},
buffer: (widget: VNAnimatedImage, _, nextValue: Buffer) => {
const movie = new QMovie();
movie.loadFromData(nextValue);
widget.setMovie(movie);
widget.movie()?.start();
},
};

/** @internal */
export class VNAnimatedImage extends QLabel implements VNWidget<AnimatedImageProps> {
insertChild() {
throw new Error('Cannot add child to animated image elements');
}

patchProp(
key: keyof AnimatedImageProps,
prevValue: Prop<AnimatedImageProps, typeof key>,
nextValue: Prop<AnimatedImageProps, typeof key>,
) {
const propSetter = animatedImagePropsSetters[key];
if (propSetter !== undefined) { propSetter(this, prevValue as never, nextValue as never); }
}

removeChild() {
throw new Error('Cannot remove/add child to animated image elements');
}

insertBefore() {
throw new Error('Cannot add child to animated image elements');
}

getNextSibling(): NodeWidget<any> | null {
throw new Error('animated image cannot have children');
}
}
12 changes: 12 additions & 0 deletions src/widgets/AnimatedImage/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { VNAnimatedImage, AnimatedImageProps } from './VNAnimatedImage';
import { WidgetConfig } from '../config';

class AnimatedImageConfig implements WidgetConfig<AnimatedImageProps> {
parentNode: any;

createElement() {
return new VNAnimatedImage();
}
}

export default AnimatedImageConfig;
4 changes: 3 additions & 1 deletion src/widgets/nativeWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export type ValidNativeWidgets = 'vn-image' |
'vn-spinbox' |
'vn-progress-bar' |
'vn-combobox' |
'vn-dial';
'vn-dial' |
'vn-animated-image';

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

export const isNativeWidget = (type: ValidNativeWidgets) => !!nativeWidgets[type];
2 changes: 2 additions & 0 deletions src/widgets/widgetMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import SpinBoxConfig from './SpinBox';
import ProgressBarConfig from './ProgressBar';
import ComboBoxConfig from './ComboBox';
import DialConfig from './Dial';
import AnimatedImageConfig from './AnimatedImage';
import { ValidNativeWidgets } from './nativeWidget';
import { WidgetConfig } from './config';

Expand All @@ -32,6 +33,7 @@ const widgetMap: WidgetMap = {
'vn-progress-bar': new ProgressBarConfig(),
'vn-combobox': new ComboBoxConfig(),
'vn-dial': new DialConfig(),
'vn-animated-image': new AnimatedImageConfig(),
};

const getConfigByType = (type: ValidNativeWidgets) => {
Expand Down
173 changes: 173 additions & 0 deletions website/docs/api/interfaces/animatedimageprops.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
---
id: "animatedimageprops"
title: "AnimatedImageProps"
sidebar_label: "AnimatedImageProps"
---

The animated image widget allows users to create and render native GIFs, video (without controls)
elements in the app.
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)

## Usage

```html
<template>
<vn-view>
<vn-animated-image :src="'https://i.giphy.com/media/oYtVHSxngR3lC/giphy.gif'" />
</vn-view>
</template>

<script>
export default { }
</script>
```

## What it looks like?

![animated-image-demo](/img/vn-animated-image.gif)

## Props and styling

You can find all the props `vn-animated-image` accepts listed below.
Apart from this, you can take a look at the [styling](/docs/guides/3-styling)
and [event handling](/docs/guides/5-handle-events) docs

## Hierarchy

↳ [TextProps](textprops.md)

↳ **AnimatedImageProps**

## Index

### Properties

* [buffer](animatedimageprops.md#optional-buffer)
* [enabled](animatedimageprops.md#optional-enabled)
* [id](animatedimageprops.md#optional-id)
* [mouseTracking](animatedimageprops.md#optional-mousetracking)
* [openExternalLinks](animatedimageprops.md#optional-openexternallinks)
* [scaledContents](animatedimageprops.md#optional-scaledcontents)
* [src](animatedimageprops.md#optional-src)
* [style](animatedimageprops.md#optional-style)
* [styleSheet](animatedimageprops.md#optional-stylesheet)
* [visible](animatedimageprops.md#optional-visible)
* [windowOpacity](animatedimageprops.md#optional-windowopacity)
* [windowTitle](animatedimageprops.md#optional-windowtitle)
* [wordWrap](animatedimageprops.md#optional-wordwrap)

## Properties

### `Optional` buffer

• **buffer**? : *Buffer*

___

### `Optional` enabled

• **enabled**? : *undefined | false | true*

*Inherited from [ViewProps](viewprops.md).[enabled](viewprops.md#optional-enabled)*

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)

___

### `Optional` id

• **id**? : *undefined | string*

*Inherited from [ViewProps](viewprops.md).[id](viewprops.md#optional-id)*

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)

___

### `Optional` mouseTracking

• **mouseTracking**? : *undefined | false | true*

*Inherited from [ViewProps](viewprops.md).[mouseTracking](viewprops.md#optional-mousetracking)*

Sets the property that tells whether mouseTracking is enabled for the widget. [QWidget: setMouseTracking](https://docs.nodegui.org/docs/api/NodeWidget#widgetsetmousetrackingismousetracked)

___

### `Optional` openExternalLinks

• **openExternalLinks**? : *undefined | false | true*

*Inherited from [TextProps](textprops.md).[openExternalLinks](textprops.md#optional-openexternallinks)*

___

### `Optional` scaledContents

• **scaledContents**? : *undefined | false | true*

*Inherited from [TextProps](textprops.md).[scaledContents](textprops.md#optional-scaledcontents)*

___

### `Optional` src

• **src**? : *undefined | string*

___

### `Optional` style

• **style**? : *undefined | string*

*Inherited from [ViewProps](viewprops.md).[style](viewprops.md#optional-style)*

Sets the inline stylesheet property. [QWidget: setInlineStyle](https://docs.nodegui.org/docs/api/NodeWidget#widgetsetinlinestylestyle)

___

### `Optional` styleSheet

• **styleSheet**? : *undefined | string*

*Inherited from [ViewProps](viewprops.md).[styleSheet](viewprops.md#optional-stylesheet)*

Sets the property that holds the widget's style sheet. [QWidget: setStyleSheet](https://docs.nodegui.org/docs/api/NodeWidget#widgetsetstylesheetstylesheet)

___

### `Optional` visible

• **visible**? : *undefined | false | true*

*Inherited from [ViewProps](viewprops.md).[visible](viewprops.md#optional-visible)*

Shows or hides the widget and its children. [QWidget: show](https://docs.nodegui.org/docs/api/NodeWidget#widgetshow)

___

### `Optional` windowOpacity

• **windowOpacity**? : *undefined | number*

*Inherited from [ViewProps](viewprops.md).[windowOpacity](viewprops.md#optional-windowopacity)*

This property holds the level of opacity for the window. [QWidget: setWindowOpacity](https://docs.nodegui.org/docs/api/NodeWidget#widgetsetwindowopacityopacity)

___

### `Optional` windowTitle

• **windowTitle**? : *undefined | string*

*Inherited from [ViewProps](viewprops.md).[windowTitle](viewprops.md#optional-windowtitle)*

Sets the window title property. [QWidget: setWindowTitle](https://docs.nodegui.org/docs/api/NodeWidget#widgetsetwindowtitletitle)

___

### `Optional` wordWrap

• **wordWrap**? : *undefined | false | true*

*Inherited from [TextProps](textprops.md).[wordWrap](textprops.md#optional-wordwrap)*
Loading