Skip to content

Commit 8f4392c

Browse files
Merge pull request #145 from renderforest/new-methods
✨ release 0.3.6 : new screen, area methods
2 parents 3310e67 + a7fad2d commit 8f4392c

File tree

9 files changed

+266
-37
lines changed

9 files changed

+266
-37
lines changed

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ Welcome to the Renderforest API! You can use our API to:
4545
- [Set voice-over](#set-voice-over)
4646
- [Set mute music](#set-mute-music)
4747
- [Set sounds](#set-sounds)
48+
- [Set screen duration](#set-screen-duration)
49+
- [Set icon position](#set-the-icon-position)
4850
- [Set text on text holder area](#set-text-on-text-holder-area)
4951
- [Set image on image holder area](#set-image-on-image-holder-area)
5052
- [Set video on video holder area](#set-video-on-video-holder-area)
@@ -482,6 +484,46 @@ const sounds = [ sound1, sound2 ]
482484
projectDataInstance.setSounds(sounds)
483485
```
484486

487+
##### Set screen duration
488+
489+
It's possible to check if `screen` duration is adjustable, get current screen duration via `calculateScreenDuration`,
490+
get maximum possible duration for current screen, and to set your desired duration.
491+
```js
492+
const screens = projectDataInstance.getScreens()
493+
494+
if (screens && screens[0]) {
495+
const isAdjustable = screens[0].isDurationAdjustable()
496+
497+
if (isAdjustable) {
498+
const calculateDuration = screens[0].calculateScreenDuration()
499+
console.log(calculateDuration)
500+
const maxDuration = screens[0].getMaxPossibleDuration()
501+
const desiredDuration = 5
502+
503+
if (desiredDuration <= maxDuration) {
504+
screens[0].setDuration(desiredDuration)
505+
}
506+
}
507+
}
508+
```
509+
510+
##### Set icon position
511+
512+
There is two methods `isIconPositionAdjustable` and `toggleIconPosition`.
513+
The first one checks if it's possible to adjust icon position. If it returns `0` then it's not possible,
514+
if a number is greater than `0` it means that icon position is adjustable.
515+
The value `1` stands for the right position, accordingly, the value `2` stands for left position.
516+
For changing the icon position here is `toggleIconPosition` method. It changes icon position value `1<-->2`.
517+
```js
518+
const screens = projectDataInstance.getScreens()
519+
520+
if (screens && screens[0]) {
521+
if (screens[0].isIconPositionAdjustable()) {
522+
screens[0].toggleIconPosition()
523+
}
524+
}
525+
```
526+
485527
##### Set text on text holder area
486528
```js
487529
const screens = projectDataInstance.getScreens()

examples/project-data/update-project-data-partial-advanced.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,41 @@ async function sample () {
5252
voiceOver: false
5353
}
5454

55-
const sounds = [ sound1, sound2 ]
55+
const sounds = [sound1, sound2]
5656
projectDataInstance.setSounds(sounds)
5757

5858
const screens = projectDataInstance.getScreens()
5959
// set text on text holder area
6060
if (screens && screens[0]) {
61+
// check if screen duration is adjustable do some manipulations
62+
const isAdjustable = screens[0].isDurationAdjustable()
63+
64+
if (isAdjustable) {
65+
const calculateDuration = screens[0].calculateScreenDuration()
66+
console.log(calculateDuration)
67+
const maxDuration = screens[0].getMaxPossibleDuration()
68+
const desiredDuration = 5
69+
70+
if (desiredDuration <= maxDuration) {
71+
screens[0].setDuration(desiredDuration)
72+
}
73+
}
74+
// check if icon position is adjustable, then change the icon position
75+
if (screens[0].isIconPositionAdjustable()) {
76+
screens[0].toggleIconPosition()
77+
}
78+
6179
const areas = screens[0].getAreas()
6280

6381
const area = areas[0]
6482
if (area && area.type === 'text') {
65-
area.setText('sample text')
83+
// check recommended character count for current area
84+
const recommendedCharacterCount = area.getRecommendedCharacterCount()
85+
const sampleText = 'sample text'
86+
87+
if (sampleText.length <= recommendedCharacterCount) {
88+
area.setText(sampleText)
89+
}
6690
}
6791
}
6892
// set image on image holder area
@@ -145,7 +169,7 @@ async function sample () {
145169
areas: [
146170
{
147171
id: 3562168,
148-
cords: [ 656, 224, 1048, 224, 1048, 332, 656, 332 ],
172+
cords: [656, 224, 1048, 224, 1048, 332, 656, 332],
149173
height: 108,
150174
order: 0,
151175
title: 'char_Angry_2',

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@renderforest/sdk-node",
33
"description": "Renderforest SDK for Node.js",
4-
"version": "0.3.5",
4+
"version": "0.3.6",
55
"author": "RenderForest LLC",
66
"bugs": {
77
"url": "https://github.com/renderforest/renderforest-sdk-node/issues"

src/classes/project-data.js

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,18 @@
88

99
const PackageJson = require('../../package.json')
1010

11-
const { MissingOrderError } = require('../util/error')
11+
const {
12+
CharacterBasedDurationError,
13+
DurationGreaterThanMaxPossibleError,
14+
IconAdjustableError,
15+
MissingOrderError,
16+
ScreenHasVideoAreaError
17+
} = require('../util/error')
18+
const screenDurationUtil = require('../util/screen-duration')
1219
const projectDataUtil = require('../util/project-data')
1320

21+
const { AVERAGE_CHARS_IN_WORD } = require('../config/config')
22+
1423
class ProjectData {
1524
/**
1625
* @constructor
@@ -218,14 +227,18 @@ class ProjectData {
218227
/**
219228
* @param {Object} screen
220229
* @returns {Object}
221-
* @description Construct screen.
230+
* @description Construct screen, adds methods to `screen` object.
222231
*/
223232
constructScreen (screen) {
224233
const {
225234
id, characterBasedDuration, compositionName, duration, extraVideoSecond, gifBigPath, gifPath, gifThumbnailPath,
226235
hidden, iconAdjustable, isFull, maxDuration, order, path, tags, title, type, areas
227236
} = screen
228237

238+
/**
239+
* @namespace screen
240+
* @description The screen object with it's methods.
241+
*/
229242
return {
230243
id,
231244
characterBasedDuration,
@@ -245,10 +258,81 @@ class ProjectData {
245258
title,
246259
type,
247260
areas,
248-
getAreas: () => {
249-
return areas.map((area) => {
250-
return this.constructArea(area)
251-
})
261+
/**
262+
* @returns {Object}
263+
* @description Maps through areas array and adds it's methods.
264+
*/
265+
getAreas: () => areas.map((area) => this.constructArea(area)),
266+
/**
267+
* @throws {ScreenHasVideoAreaError}
268+
* @return {Object.characterBasedDuration}
269+
* @description Checks if `screen` has video area, then throws error.
270+
* Otherwise returns `characterBasedDuration`.
271+
*/
272+
isDurationAdjustable: () => {
273+
const videoAreas = areas.filter((area) => area.type === 'video')
274+
275+
if (videoAreas.length > 0) {
276+
throw new ScreenHasVideoAreaError('The screen has video area.')
277+
}
278+
279+
return characterBasedDuration
280+
},
281+
/**
282+
* @return {number}
283+
* @description Calculates screen duration using screen duration utility.
284+
* Detailed description can be found in screen duration util.
285+
*/
286+
calculateScreenDuration: () => screenDurationUtil.getScreenDuration(screen),
287+
/**
288+
* @returns {number}
289+
* @description Filters ares to find only video ones.
290+
* Checks if count of video areas is more than 0, then counts sum of `wordCount`s.
291+
* Otherwise returns `maxDuration` or `duration`.
292+
*/
293+
getMaxPossibleDuration: () => {
294+
const videoAreas = areas.filter((area) => area.type === 'video')
295+
296+
if (videoAreas.length > 0) {
297+
return videoAreas.reduce((acc, videoArea) => acc + videoArea.wordCount, 0)
298+
}
299+
300+
return maxDuration || duration
301+
},
302+
/**
303+
* @param {number} duration - The new duration to set.
304+
* @throws {CharacterBasedDurationError, DurationGreaterThanMaxPossibleError}
305+
* @description Checks if `characterBasedDuration` is falsy, then throws error.
306+
* If `duration` is more than maximum possible duration, then throws error.
307+
* Otherwise sets `selectedDuration`.
308+
*/
309+
setDuration: function (duration) {
310+
if (!characterBasedDuration) {
311+
throw new CharacterBasedDurationError('Current screen\'s duration is not adjustable.')
312+
}
313+
314+
if (duration > this.getMaxPossibleDuration()) {
315+
throw new DurationGreaterThanMaxPossibleError('Given `value` is greater than maximum possible duration.')
316+
}
317+
318+
this.selectedDuration = duration
319+
},
320+
/**
321+
* @return {boolean}
322+
* @description Checks if icon position is adjustable by double negation.
323+
*/
324+
isIconPositionAdjustable: () => iconAdjustable,
325+
/**
326+
* @throws {IconAdjustableError}
327+
* @description Checks if icon position is not adjustable then throws error.
328+
* Otherwise does `xor` bitwise operation with `iconAdjustable` and 3.
329+
* Number `3` stands for converting 1->2 and 2->1.
330+
*/
331+
toggleIconPosition: function () {
332+
if (!this.isIconPositionAdjustable()) {
333+
throw new IconAdjustableError('Icon position is not adjustable.')
334+
}
335+
this.iconAdjustable ^= 3
252336
}
253337
}
254338
}
@@ -271,6 +355,8 @@ class ProjectData {
271355
area.value = text
272356
this.patchProperties.push('screens')
273357
}
358+
359+
result.getRecommendedCharacterCount = () => Math.floor(parseInt(wordCount) * AVERAGE_CHARS_IN_WORD)
274360
}
275361

276362
if (area.type === 'image') {

src/config/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const PackageJson = require('../../package.json')
33
const config = {
44
API_HOST: 'https://api.renderforest.com',
55
API_PREFIX: '/api/v1',
6+
AVERAGE_CHARS_IN_WORD: 5.5,
67
HTTP_DEFAULT_OPTIONS: {
78
method: 'GET',
89
json: true,

src/util/error.js

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,27 @@
66
* LICENSE file in the root directory.
77
*/
88

9-
class RenderforestError extends Error {
10-
constructor (message) {
11-
super()
12-
this.message = message
13-
this.name = this.constructor.name
14-
}
15-
}
9+
const CUSTOM_ERRORS = [
10+
'CharacterBasedDurationError',
11+
'DurationGreaterThanMaxPossibleError',
12+
'IconAdjustableError',
13+
'MissingOrderError',
14+
'RenderforestError',
15+
'ScreenHasVideoAreaError',
16+
'ScreenIdAlreadyExistsError'
17+
]
1618

17-
class MissingOrderError extends Error {
18-
constructor (message) {
19-
super()
20-
this.message = message
21-
this.name = this.constructor.name
22-
}
23-
}
19+
const ERRORS = CUSTOM_ERRORS.reduce((acc, className) => {
20+
acc[className] = ({
21+
[className]: class extends Error {
22+
constructor (msg) {
23+
super(msg)
24+
this.name = this.constructor.name
25+
}
26+
}
27+
})[className]
2428

25-
module.exports = {
26-
RenderforestError,
27-
MissingOrderError
28-
}
29+
return acc
30+
}, {})
31+
32+
module.exports = ERRORS

src/util/project-data.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
const { ScreenIdAlreadyExistsError } = require('../util/error')
2+
13
/**
24
* @param {Object} screen - The screen to normalize.
35
* @param {Number} index - The value to set.
46
* @returns {Object}
57
* @description Sets `screen.order` value to given `index`.
68
*/
7-
function normalizeOrders (screen, index) {
9+
const normalizeOrders = (screen, index) => {
810
screen.order = index
911
return screen
1012
}
@@ -15,19 +17,15 @@ function normalizeOrders (screen, index) {
1517
* @description Sort factory.
1618
* Sorting function which sorts with given `prop`.
1719
*/
18-
function sortFactory (prop) {
19-
return function (a, b) {
20-
return parseInt(a[prop]) - parseInt(b[prop])
21-
}
22-
}
20+
const sortFactory = (prop) => (a, b) => parseInt(a[prop]) - parseInt(b[prop])
2321

2422
/**
2523
* @param {Array} screens - The screens array.
2624
* @param {Object} newScreen - The screen to insert.
2725
* @returns {Array}
2826
* @description Inserts screen at the right order.
2927
*/
30-
function insertScreenAtOrder (screens, newScreen) {
28+
const insertScreenAtOrder = (screens, newScreen) => {
3129
if (screens.length === 0) {
3230
return [newScreen]
3331
}
@@ -53,14 +51,27 @@ function insertScreenAtOrder (screens, newScreen) {
5351
}, [])
5452
}
5553

54+
/**
55+
* @param {Array} screens - The screens array.
56+
* @param {Object} newScreen - The screen to insert.
57+
* @return {boolean}
58+
* @description Checks if there is already `screen` with given id, then returns `false`, otherwise `true`.
59+
*/
60+
const ifNewScreenIdExists = (screens, newScreen) =>
61+
screens.findIndex(screen => screen.id === newScreen.id) < 0
62+
5663
/**
5764
* @param {Array} screens - The screens array.
5865
* @param {Object} newScreen - The screen to insert.
5966
* @returns {Array}
6067
* @description Inserting new screen, arranges screens by `screen.order`
6168
* and normalize orders to have consequent numbers.
6269
*/
63-
function insertAndNormalizeOrder (screens, newScreen) {
70+
const insertAndNormalizeOrder = (screens, newScreen) => {
71+
if (!ifNewScreenIdExists(screens, newScreen)) {
72+
throw new ScreenIdAlreadyExistsError('There is already one screen with current `screen.id`.')
73+
}
74+
6475
return insertScreenAtOrder(screens, newScreen)
6576
.sort(sortFactory('order'))
6677
.map(normalizeOrders)

0 commit comments

Comments
 (0)