@vixoniccom/menu-daily 0.2.0-dev.0 → 0.2.0-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/npm-publish.yml +105 -0
- package/.github/workflows/sonarqube.yml +30 -0
- package/.vscode/settings.json +5 -1
- package/CHANGELOG.md +18 -0
- package/build/index.html +1 -1
- package/build/main.js +1 -1
- package/build.zip +0 -0
- package/package.json +1 -1
- package/sonar-project.properties +1 -0
- package/src/index.html +33 -33
- package/src/logger.ts +3 -3
- package/src/main.ts +8 -8
- package/src/scenes/App.tsx +27 -29
- package/src/scenes/components/FormattedText.tsx +9 -7
- package/src/scenes/components/Grid/Grid.tsx +28 -26
- package/src/scenes/components/Grid/GridItem.tsx +16 -14
- package/src/scenes/components/MealContainer/components/Title/index.tsx +5 -4
- package/src/scenes/components/MealContainer/index.tsx +1 -2
package/build.zip
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
sonar.projectKey=Vixonic_store-menu-daily_1e47740b-90ac-4376-9fb7-5d97065b6387
|
package/src/index.html
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
<!
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
</head>
|
|
28
|
-
<body>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
</body>
|
|
33
|
-
</html>
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<title></title>
|
|
5
|
+
<meta charset="utf-8" />
|
|
6
|
+
<style>
|
|
7
|
+
@font-face {
|
|
8
|
+
font-family: 'FrutigerLTStdBoldCn';
|
|
9
|
+
src: url('./static/fonts/FrutigerLTStdBoldCn.ttf');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@font-face {
|
|
13
|
+
font-family: 'FrutigerLTStdCn';
|
|
14
|
+
src: url('./static/fonts/FrutigerLTStdCn.otf');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@font-face {
|
|
18
|
+
font-family: 'FrutigerLTStdBlackCn';
|
|
19
|
+
src: url('./static/fonts/FrutigerLTStdBlackCn.ttf');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@font-face {
|
|
23
|
+
font-family: 'FrutigerLTStdLightCn';
|
|
24
|
+
src: url('./static/fonts/FrutigerLTStdLightCn.ttf');
|
|
25
|
+
}
|
|
26
|
+
</style>
|
|
27
|
+
</head>
|
|
28
|
+
<body>
|
|
29
|
+
<div
|
|
30
|
+
id="root"
|
|
31
|
+
style="position: absolute; top: 0; left: 0; bottom: 0; right: 0; display: flex; justify-content: center; align-items: center; overflow: hidden"></div>
|
|
32
|
+
</body>
|
|
33
|
+
</html>
|
package/src/logger.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export const LOGGER_PROPERTY = 'vxAppLogger'
|
|
2
2
|
class Logger {
|
|
3
|
-
log
|
|
4
|
-
if ((window as any)[LOGGER_PROPERTY] === true) {
|
|
3
|
+
log(message: any, ...optionalParams: any[]) {
|
|
4
|
+
if ((globalThis.window as any)[LOGGER_PROPERTY] === true) {
|
|
5
5
|
if (optionalParams && optionalParams.length > 0) console.log(message, optionalParams)
|
|
6
6
|
else console.log(message)
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export
|
|
11
|
+
export const logger = new Logger()
|
package/src/main.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
import React from 'react'
|
|
3
|
-
import
|
|
4
|
-
|
|
3
|
+
import { createRoot } from 'react-dom/client'
|
|
5
4
|
import App, { AppProps } from './scenes/App'
|
|
6
5
|
import { logger } from './logger'
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
const { ipcRenderer } = require('electron')
|
|
9
8
|
|
|
10
9
|
let start = false
|
|
11
10
|
let vixonicData: VixonicData
|
|
11
|
+
const root = createRoot(document.getElementById('root')!)
|
|
12
12
|
|
|
13
13
|
ipcRenderer.on('preload', (_event: any, _data: VixonicData) => {
|
|
14
14
|
// Preload command
|
|
15
15
|
logger.log('Preload', _data)
|
|
16
16
|
vixonicData = _data
|
|
17
|
-
|
|
17
|
+
render()
|
|
18
18
|
})
|
|
19
19
|
|
|
20
20
|
ipcRenderer.on('start', (_event: any, _data: VixonicData) => {
|
|
@@ -22,21 +22,21 @@ ipcRenderer.on('start', (_event: any, _data: VixonicData) => {
|
|
|
22
22
|
logger.log('Start', _data)
|
|
23
23
|
vixonicData = _data
|
|
24
24
|
start = true
|
|
25
|
-
|
|
25
|
+
render()
|
|
26
26
|
})
|
|
27
27
|
|
|
28
28
|
ipcRenderer.on('update', (_event: any, _data: VixonicData) => {
|
|
29
29
|
// Update command
|
|
30
30
|
logger.log('Update', _data)
|
|
31
31
|
vixonicData = _data
|
|
32
|
-
|
|
32
|
+
render()
|
|
33
33
|
})
|
|
34
34
|
|
|
35
35
|
ipcRenderer.on('finish', (_event: any) => {
|
|
36
36
|
// Finish command.
|
|
37
37
|
})
|
|
38
38
|
|
|
39
|
-
function
|
|
39
|
+
function render () {
|
|
40
40
|
if (!vixonicData) return
|
|
41
|
-
|
|
41
|
+
root.render(React.createElement<AppProps>(App as any, { start, vixonicData }))
|
|
42
42
|
}
|
package/src/scenes/App.tsx
CHANGED
|
@@ -35,7 +35,7 @@ const resolveTodayMenu = (vixonicData: VixonicData): TodayMenu => {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
class App extends React.Component<AppProps> {
|
|
38
|
-
render
|
|
38
|
+
render() {
|
|
39
39
|
const { parameters, downloadsPath } = this.props.vixonicData
|
|
40
40
|
let cycle = parameters.animationDuration && parameters.animationDuration * 1000 || 15000
|
|
41
41
|
const { status, data, error } = resolveTodayMenu(this.props.vixonicData)
|
|
@@ -45,13 +45,29 @@ class App extends React.Component<AppProps> {
|
|
|
45
45
|
position: 'absolute',
|
|
46
46
|
top: 0, right: 0, bottom: 0, left: 0,
|
|
47
47
|
backgroundImage: parameters.backgroundImage &&
|
|
48
|
-
|
|
48
|
+
`url("${downloadsPath + '/' + parameters.backgroundImage.filename}")` || undefined,
|
|
49
49
|
backgroundSize: '100% 100%',
|
|
50
50
|
padding: parameters.containerGridMargins
|
|
51
51
|
}}>
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
{data?.[0] ?
|
|
53
|
+
<Grid
|
|
54
|
+
animate={this.props.start}
|
|
55
|
+
style={{ width: '100%', height: '100%' }}
|
|
56
|
+
items={data.map((meal) => (<MealContainer key={meal.type} data={meal} interval={cycle} vixonicData={this.props.vixonicData} />))}
|
|
57
|
+
animationConfig={{
|
|
58
|
+
mode: parameters.animationMode || 'fade',
|
|
59
|
+
duration: cycle
|
|
60
|
+
}} layout={{
|
|
61
|
+
alignment: {
|
|
62
|
+
h: 'start',
|
|
63
|
+
v: 'center'
|
|
64
|
+
},
|
|
65
|
+
columns: parameters.containerGridColumns || 1,
|
|
66
|
+
columnsGap: parameters.containerGridColumnsGap || 0,
|
|
67
|
+
rows: parameters.containerGridRows || 1,
|
|
68
|
+
rowsGap: parameters.containerGridRowsGap || 0
|
|
69
|
+
}} /> :
|
|
70
|
+
<div style={{ width: '100%', height: '100%', display: 'flex', fontSize: `${100 / (parameters.itemGridRows || 1)}vmin`, justifyContent: 'center', alignItems: 'center' }}>
|
|
55
71
|
<FormattedText
|
|
56
72
|
text={placeholder}
|
|
57
73
|
defaults={{
|
|
@@ -59,31 +75,13 @@ class App extends React.Component<AppProps> {
|
|
|
59
75
|
fontColor: 'black',
|
|
60
76
|
fontSize: 10
|
|
61
77
|
}}
|
|
62
|
-
style={{width: '100%'}}
|
|
78
|
+
style={{ width: '100%' }}
|
|
63
79
|
format={parameters.itemOptionsTextFormat || {}}
|
|
64
|
-
unit='%'/>
|
|
65
|
-
</div>
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
style={{width: '100%', height: '100%'}}
|
|
70
|
-
items={data.map((meal) => (<MealContainer key={meal.type} data={meal} interval={cycle} vixonicData={this.props.vixonicData} />))}
|
|
71
|
-
animation={{
|
|
72
|
-
mode: parameters.animationMode || 'fade',
|
|
73
|
-
duration: cycle
|
|
74
|
-
}} layout={{
|
|
75
|
-
alignment: {
|
|
76
|
-
h: 'start',
|
|
77
|
-
v: 'center'
|
|
78
|
-
},
|
|
79
|
-
columns: parameters.containerGridColumns || 1,
|
|
80
|
-
columnsGap: parameters.containerGridColumnsGap || 0,
|
|
81
|
-
rows: parameters.containerGridRows || 1,
|
|
82
|
-
rowsGap: parameters.containerGridRowsGap || 0
|
|
83
|
-
}}/>
|
|
84
|
-
}
|
|
85
|
-
<FontLoader downloadPath={downloadsPath} fonts={fontParser(parameters)}/>
|
|
86
|
-
</div>
|
|
80
|
+
unit='%' />
|
|
81
|
+
</div>
|
|
82
|
+
}
|
|
83
|
+
<FontLoader downloadPath={downloadsPath} fonts={fontParser(parameters)} />
|
|
84
|
+
</div>
|
|
87
85
|
}
|
|
88
86
|
}
|
|
89
87
|
|
|
@@ -22,13 +22,15 @@ type Props = {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
class FormattedText extends React.Component<Props> {
|
|
25
|
-
render
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
render() {
|
|
26
|
+
const { format, defaults } = this.props
|
|
27
|
+
const { alignment, font, fontColor, fontSize } = format
|
|
28
|
+
const containerStyle = {
|
|
29
29
|
display: 'inline-flex',
|
|
30
|
-
justifyContent: this.getHorizontalAlignment(alignment?.horizontal || defaults.alignment)
|
|
31
|
-
|
|
30
|
+
justifyContent: this.getHorizontalAlignment(alignment?.horizontal || defaults.alignment),
|
|
31
|
+
...this.props.style
|
|
32
|
+
}
|
|
33
|
+
|
|
32
34
|
return <div style={containerStyle}>
|
|
33
35
|
<span style={{
|
|
34
36
|
color: fontColor || defaults.fontColor,
|
|
@@ -44,7 +46,7 @@ class FormattedText extends React.Component<Props> {
|
|
|
44
46
|
</div>
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
getHorizontalAlignment
|
|
49
|
+
getHorizontalAlignment(alignment: any) {
|
|
48
50
|
if (alignment) {
|
|
49
51
|
return alignments.hasOwnProperty(alignment) ? (alignments as any)[alignment] : 'flex-start'
|
|
50
52
|
}
|
|
@@ -4,14 +4,14 @@ import Item from './GridItem'
|
|
|
4
4
|
|
|
5
5
|
type GridProps = {
|
|
6
6
|
animate: boolean,
|
|
7
|
-
|
|
7
|
+
animationConfig: {
|
|
8
8
|
mode: 'fade' | 'slideLeft' | 'slideRight',
|
|
9
9
|
duration: number,
|
|
10
10
|
speed?: number,
|
|
11
11
|
stagger?: number,
|
|
12
12
|
reverse?: boolean
|
|
13
13
|
},
|
|
14
|
-
layout: {
|
|
14
|
+
layout: Readonly<{
|
|
15
15
|
rows: number,
|
|
16
16
|
rowsGap?: number,
|
|
17
17
|
columns: number,
|
|
@@ -20,10 +20,9 @@ type GridProps = {
|
|
|
20
20
|
h: 'start' | 'center' | 'end',
|
|
21
21
|
v: 'start' | 'center' | 'end'
|
|
22
22
|
}
|
|
23
|
-
}
|
|
23
|
+
}>
|
|
24
24
|
style?: React.CSSProperties
|
|
25
25
|
fontSize?: string
|
|
26
|
-
id: string
|
|
27
26
|
items: React.ReactNode[]
|
|
28
27
|
}
|
|
29
28
|
|
|
@@ -54,39 +53,42 @@ class Grid extends React.Component<GridProps, GridState> {
|
|
|
54
53
|
items: []
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
constructor
|
|
58
|
-
super
|
|
56
|
+
constructor(props: GridProps) {
|
|
57
|
+
super(props)
|
|
59
58
|
this.lastIndex = 0
|
|
60
59
|
this.animation = new AnimationController()
|
|
61
60
|
}
|
|
62
61
|
|
|
63
|
-
componentDidMount
|
|
64
|
-
this.configure(
|
|
62
|
+
componentDidMount() {
|
|
63
|
+
this.configure()
|
|
65
64
|
}
|
|
66
65
|
|
|
67
|
-
componentWillUnmount
|
|
66
|
+
componentWillUnmount() {
|
|
68
67
|
this.unmounting = true
|
|
69
68
|
}
|
|
70
69
|
|
|
71
|
-
configure
|
|
72
|
-
this.
|
|
73
|
-
this.
|
|
74
|
-
this.
|
|
75
|
-
this.
|
|
76
|
-
this.
|
|
70
|
+
configure() {
|
|
71
|
+
const { animationConfig, layout, animate } = this.props
|
|
72
|
+
this.animation.configure(animationConfig)
|
|
73
|
+
this.columns = layout.columns || 1
|
|
74
|
+
this.columnsGap = layout.columnsGap || 0
|
|
75
|
+
this.rows = layout.rows || 1
|
|
76
|
+
this.rowsGap = layout.rowsGap || 0
|
|
77
77
|
this.itemsCount = this.rows * this.columns
|
|
78
|
-
if (
|
|
78
|
+
if (animate && !this.animating && this.state.stage === 'idle') {
|
|
79
79
|
this.animating = true
|
|
80
|
-
this.createItems(
|
|
80
|
+
this.createItems()
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
// Filter items by index and create the proper item within its container.
|
|
85
|
-
createItems
|
|
86
|
-
|
|
85
|
+
createItems() {
|
|
86
|
+
const { items, layout } = this.props
|
|
87
|
+
if (!items) return
|
|
88
|
+
|
|
87
89
|
let count = 0
|
|
88
|
-
this.lastIndex = this.lastIndex <
|
|
89
|
-
|
|
90
|
+
this.lastIndex = this.lastIndex < items.length ? this.lastIndex : 0
|
|
91
|
+
const newItems = items.filter((_item, index) => {
|
|
90
92
|
return index >= this.lastIndex
|
|
91
93
|
}).map((item, index, arr) => {
|
|
92
94
|
if (count >= this.itemsCount) return null
|
|
@@ -101,7 +103,7 @@ class Grid extends React.Component<GridProps, GridState> {
|
|
|
101
103
|
ic_lastChild: index === (arr.length - 1)
|
|
102
104
|
}} style={this.animation.getInitialStyle()}
|
|
103
105
|
// Item alignment. By default is center - center.
|
|
104
|
-
alignment={
|
|
106
|
+
alignment={layout.alignment}
|
|
105
107
|
// Setup item width based on columns count.
|
|
106
108
|
width={(100 - (this.columnsGap * (this.columns - 1))) / this.columns}
|
|
107
109
|
// Setup item height based on rows count. If 0 set up on auto.
|
|
@@ -129,7 +131,7 @@ class Grid extends React.Component<GridProps, GridState> {
|
|
|
129
131
|
}
|
|
130
132
|
}
|
|
131
133
|
|
|
132
|
-
render
|
|
134
|
+
render() {
|
|
133
135
|
return <div ref={(container) => { this.container = container }} style={{
|
|
134
136
|
opacity: this.state.show ? 1 : 0,
|
|
135
137
|
position: 'relative',
|
|
@@ -142,14 +144,14 @@ class Grid extends React.Component<GridProps, GridState> {
|
|
|
142
144
|
</div>
|
|
143
145
|
}
|
|
144
146
|
|
|
145
|
-
componentDidUpdate
|
|
147
|
+
componentDidUpdate(prevProps: GridProps) {
|
|
146
148
|
if (prevProps !== this.props) {
|
|
147
|
-
this.configure(
|
|
149
|
+
this.configure()
|
|
148
150
|
}
|
|
149
151
|
if (this.props.animate && this.state.stage === 'prepared') {
|
|
150
152
|
// Start animations.
|
|
151
153
|
this.animation.animate(this.container!.childNodes, () => {
|
|
152
|
-
!this.unmounting && this.createItems(
|
|
154
|
+
!this.unmounting && this.createItems()
|
|
153
155
|
})
|
|
154
156
|
this.setState({
|
|
155
157
|
stage: 'animating'
|
|
@@ -41,13 +41,23 @@ class GridItem extends React.Component<GridItemProps, any> {
|
|
|
41
41
|
this.setState({height: this.el.offsetHeight})
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
componentDidUpdate () {
|
|
45
|
+
const height = this.el.offsetHeight
|
|
46
|
+
if (height !== this.state.height) {
|
|
47
|
+
this.setState({ height })
|
|
48
|
+
}
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
render () {
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
const props = this.props
|
|
53
|
+
const { ic_rowIndex, ic_columnIndex } = props.containerData
|
|
54
|
+
const top = ic_rowIndex > 0 && props.verticalGap
|
|
55
|
+
? `${props.verticalGap * ic_rowIndex}%`
|
|
56
|
+
: '0'
|
|
57
|
+
const paddingLeft = ic_columnIndex > 0 && props.horizontalGap
|
|
58
|
+
? `${props.horizontalGap}%`
|
|
59
|
+
: '0'
|
|
60
|
+
const style: React.CSSProperties = {
|
|
51
61
|
overflow: 'hidden',
|
|
52
62
|
display: 'flex',
|
|
53
63
|
position: 'relative',
|
|
@@ -56,16 +66,8 @@ class GridItem extends React.Component<GridItemProps, any> {
|
|
|
56
66
|
width: `${props.width}%`,
|
|
57
67
|
height: `${props.height}%`,
|
|
58
68
|
fontSize: this.props.fontSize || this.state.height && `${this.state.height}px`,
|
|
59
|
-
top
|
|
60
|
-
|
|
61
|
-
: props.verticalGap
|
|
62
|
-
? `${props.verticalGap * props.containerData.ic_rowIndex}%`
|
|
63
|
-
: '0',
|
|
64
|
-
paddingLeft: props.containerData.ic_columnIndex === 0
|
|
65
|
-
? '0'
|
|
66
|
-
: props.horizontalGap
|
|
67
|
-
? `${props.horizontalGap}%`
|
|
68
|
-
: '0',
|
|
69
|
+
top,
|
|
70
|
+
paddingLeft,
|
|
69
71
|
...props.style
|
|
70
72
|
}
|
|
71
73
|
return <div style={style}
|
|
@@ -29,16 +29,17 @@ class Title extends React.Component<Props> {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
componentDidMount() {
|
|
32
|
-
this.setup(
|
|
32
|
+
this.setup()
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
setup(
|
|
36
|
-
const {
|
|
35
|
+
setup() {
|
|
36
|
+
const { vixonicData, getPadding } = this.props
|
|
37
|
+
const { parameters } = vixonicData
|
|
37
38
|
if (parameters.itemStyle && TitleStyles[parameters.itemStyle]) {
|
|
38
39
|
this.style = TitleStyles[parameters.itemStyle]
|
|
39
40
|
}
|
|
40
41
|
const fontSize = parameters.itemTitleTextFormat?.fontSize
|
|
41
|
-
|
|
42
|
+
getPadding(this.style.getPadding(fontSize || defaultFontSize))
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
render() {
|
|
@@ -38,10 +38,9 @@ export default class MealContainer extends React.Component<Props, any> {
|
|
|
38
38
|
padding: parameters.itemGridMargins || this.state.padding
|
|
39
39
|
}}
|
|
40
40
|
fontSize='inherit'
|
|
41
|
-
id={data.type}
|
|
42
41
|
items={data.options.map((option) => (<OptionItem key={option} data={option} vixonicData={vixonicData} />))}
|
|
43
42
|
animate={true}
|
|
44
|
-
|
|
43
|
+
animationConfig={{
|
|
45
44
|
mode: parameters.animationMode || 'fade',
|
|
46
45
|
duration: cycle
|
|
47
46
|
}}
|