remote-calibrator 0.3.0-beta.2 → 0.3.0-beta.7

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remote-calibrator",
3
- "version": "0.3.0-beta.2",
3
+ "version": "0.3.0-beta.7",
4
4
  "description": "A toolbox for remote testing calibration and tracking.",
5
5
  "main": "lib/RemoteCalibrator.min.js",
6
6
  "directories": {
@@ -15,7 +15,8 @@
15
15
  "build": "webpack --env=production",
16
16
  "serve": "node server.js",
17
17
  "prepare": "husky install",
18
- "netlify": "cp -r ./lib ./homepage"
18
+ "netlify": "cp -r ./lib ./homepage",
19
+ "phrases": "node i18n/fetch-languages-sheets.js && git add src/i18n.js"
19
20
  },
20
21
  "repository": {
21
22
  "type": "git",
@@ -28,28 +29,31 @@
28
29
  },
29
30
  "homepage": "https://github.com/EasyEyes/remote-calibrator#readme",
30
31
  "devDependencies": {
31
- "@babel/core": "^7.15.5",
32
+ "@babel/core": "^7.15.8",
32
33
  "autoprefixer": "^10.3.7",
33
34
  "babel-loader": "^8.2.2",
34
35
  "clean-webpack-plugin": "^4.0.0",
35
- "css-loader": "^6.3.0",
36
+ "css-loader": "^6.4.0",
36
37
  "cssnano": "^5.0.8",
37
38
  "eslint": "^7.32.0",
38
39
  "eslint-webpack-plugin": "^3.0.1",
39
40
  "express": "^4.17.1",
41
+ "googleapis": "^88.2.0",
40
42
  "husky": "^7.0.2",
41
- "lint-staged": "^11.2.0",
42
- "postcss-loader": "^6.1.1",
43
+ "lint-staged": "^11.2.3",
44
+ "nodemon": "^2.0.13",
45
+ "postcss-loader": "^6.2.0",
43
46
  "prettier": "^2.4.1",
44
47
  "sass": "^1.42.1",
45
- "sass-loader": "^12.1.0",
48
+ "sass-loader": "^12.2.0",
46
49
  "style-loader": "^3.3.0",
47
50
  "svg-inline-loader": "^0.8.2",
48
51
  "terser-webpack-plugin": "^5.2.4",
49
52
  "url-loader": "^4.1.1",
50
- "webpack": "^5.57.1",
51
- "webpack-cli": "^4.8.0",
52
- "webpack-modules": "^1.0.0"
53
+ "webpack": "^5.58.2",
54
+ "webpack-cli": "^4.9.0",
55
+ "webpack-modules": "^1.0.0",
56
+ "xlsx": "^0.17.3"
53
57
  },
54
58
  "lint-staged": {
55
59
  "*.js": "eslint --cache --fix",
@@ -1,6 +1,7 @@
1
+ import { phrases } from '../i18n'
1
2
  import '../css/buttons.scss'
2
3
 
3
- export const addButtons = (parent, { go, cancel }, showCancelButton) => {
4
+ export const addButtons = (RCL, parent, { go, cancel }, showCancelButton) => {
4
5
  const buttons = document.createElement('div')
5
6
  buttons.className = 'rc-buttons'
6
7
  buttons.id = 'rc-buttons'
@@ -11,7 +12,7 @@ export const addButtons = (parent, { go, cancel }, showCancelButton) => {
11
12
  goButton = document.createElement('button')
12
13
  goButton.className = 'rc-button rc-go-button'
13
14
  goButton.onclick = go
14
- goButton.innerHTML = 'OK'
15
+ goButton.innerHTML = phrases.RC_ok[RCL]
15
16
  buttons.appendChild(goButton)
16
17
  }
17
18
 
@@ -19,7 +20,7 @@ export const addButtons = (parent, { go, cancel }, showCancelButton) => {
19
20
  cancelButton = document.createElement('button')
20
21
  cancelButton.className = 'rc-button rc-cancel-button'
21
22
  cancelButton.onclick = cancel
22
- cancelButton.innerHTML = 'Cancel'
23
+ cancelButton.innerHTML = phrases.RC_cancel[RCL]
23
24
  buttons.appendChild(cancelButton)
24
25
  }
25
26
 
@@ -0,0 +1,31 @@
1
+ import { phrases } from '../i18n'
2
+
3
+ export function looseSetLanguage(lang) {
4
+ const originalKeys = Object.keys(phrases.EE_languageNameNative)
5
+ if (originalKeys.includes(lang)) return constructLangData(lang)
6
+
7
+ const shortKeys = []
8
+ originalKeys.forEach(l => {
9
+ shortKeys.push(l.split('-')[0])
10
+ })
11
+
12
+ const shortLang = lang.split('-')[0].toLowerCase()
13
+
14
+ if (shortKeys.includes(shortLang))
15
+ return constructLangData(originalKeys[shortKeys.indexOf(shortLang)])
16
+
17
+ return constructLangData('en-US')
18
+ }
19
+
20
+ function constructLangData(lang) {
21
+ return {
22
+ value: {
23
+ language: lang,
24
+ languageNameEnglish: phrases.EE_languageNameEnglish[lang],
25
+ languageNameNative: phrases.EE_languageNameNative[lang],
26
+ languageDirection: phrases.EE_languageDirection[lang],
27
+ languagePhraseSource: phrases.EE_phraseSource[lang],
28
+ },
29
+ timestamp: new Date(),
30
+ }
31
+ }
@@ -1,3 +1,5 @@
1
+ import { phrases } from '../i18n'
2
+
1
3
  export const swalInfoOptions = RC => {
2
4
  return {
3
5
  icon: 'info',
@@ -5,7 +7,7 @@ export const swalInfoOptions = RC => {
5
7
  allowEnterKey: false,
6
8
  allowOutsideClick: false,
7
9
  showConfirmButton: true,
8
- confirmButtonText: 'OK',
10
+ confirmButtonText: phrases.RC_ok[RC.L],
9
11
  showClass: {
10
12
  popup: 'animate__animated animate__fadeInUp',
11
13
  // backdrop: 'animate__animated animate__fadeIn',
@@ -19,7 +21,7 @@ export const swalInfoOptions = RC => {
19
21
  customClass: {
20
22
  icon: 'my__swal2__icon',
21
23
  title: 'my__swal2__title',
22
- htmlContainer: 'my__swal2__html',
24
+ htmlContainer: 'my__swal2__html' + ` rc-lang-${RC.LD.toLowerCase()}`,
23
25
  },
24
26
  }
25
27
  }
@@ -98,9 +98,15 @@ export function getFullscreen() {
98
98
 
99
99
  /* -------------------------------------------------------------------------- */
100
100
 
101
- export function constructInstructions(headline, description = null) {
101
+ export function constructInstructions(
102
+ headline,
103
+ description = null,
104
+ scrollable = false
105
+ ) {
102
106
  return (
103
- `<div class="calibration-instruction"><h1>${headline}</h1>` +
107
+ `<div class="calibration-instruction${
108
+ scrollable ? ' calibration-instruction-scrollable' : ''
109
+ }"><h1>${headline}</h1>` +
104
110
  (description
105
111
  ? `<p class="calibration-description">${description}</p></div>`
106
112
  : '')
package/src/const.js CHANGED
@@ -14,17 +14,17 @@ RemoteCalibrator.prototype._CONST = Object.freeze({
14
14
  },
15
15
  },
16
16
  S: {
17
+ AUTO: 'AUTO',
17
18
  CLICK_TYPE: {
18
19
  MOUSE: 'mouse',
19
20
  TOUCH: 'touch',
20
21
  },
21
22
  },
22
23
  COLOR: {
24
+ LIGHT_GREY: '#cccccc',
23
25
  ORANGE: '#ff9a00',
24
26
  DARK_RED: '#ac0d0d',
25
27
  },
26
- CREDIT_TEXT: {
27
- BLIND_SPOT_TEST: `As suggested by the Li et al. (2020) "Virtual Chinrest" paper.`,
28
- CREDIT_CARD: `Credit card suggested by the Li et al. (2020) "Virtual Chinrest" paper.`,
29
- },
28
+ LTR: 'LTR',
29
+ RTL: 'RTL',
30
30
  })
package/src/core.js CHANGED
@@ -9,7 +9,13 @@ import DeviceDetector from 'device-detector-js'
9
9
 
10
10
  import randomPhrases from './components/randomPhrases'
11
11
  import { debug } from './debug'
12
- import { getFullscreen, blurAll, constructInstructions } from './helpers'
12
+ import {
13
+ getFullscreen,
14
+ blurAll,
15
+ constructInstructions,
16
+ } from './components/utils'
17
+ import { looseSetLanguage } from './components/language'
18
+ import { phrases } from './i18n'
13
19
 
14
20
  class RemoteCalibrator {
15
21
  constructor() {
@@ -29,6 +35,9 @@ class RemoteCalibrator {
29
35
 
30
36
  this._id = null
31
37
 
38
+ this._lang = null // A single string, e.g., 'en-US'
39
+ this._langData = []
40
+
32
41
  this._environmentData = []
33
42
 
34
43
  this._displayData = [] // Px
@@ -76,6 +85,7 @@ class RemoteCalibrator {
76
85
  ////
77
86
 
78
87
  get id() {
88
+ if (!this._id) return null
79
89
  return {
80
90
  value: this._id.value,
81
91
  timestamp: this._id.timestamp,
@@ -100,6 +110,47 @@ class RemoteCalibrator {
100
110
  }
101
111
  }
102
112
 
113
+ get supportedLanguages() {
114
+ const a = []
115
+ for (let l in phrases.EE_languageNameEnglish) {
116
+ a.push({
117
+ language: l,
118
+ languageNameEnglish: phrases.EE_languageNameEnglish[l],
119
+ languageNameNative: phrases.EE_languageNameNative[l],
120
+ })
121
+ }
122
+
123
+ return a
124
+ }
125
+
126
+ get L() {
127
+ return this._lang
128
+ }
129
+
130
+ get LD() {
131
+ return this.languageDirection.value
132
+ }
133
+
134
+ get language() {
135
+ return this._helper_get(this._langData, 'language')
136
+ }
137
+
138
+ get languageNameEnglish() {
139
+ return this._helper_get(this._langData, 'languageNameEnglish')
140
+ }
141
+
142
+ get languageNameNative() {
143
+ return this._helper_get(this._langData, 'languageNameNative')
144
+ }
145
+
146
+ get languageDirection() {
147
+ return this._helper_get(this._langData, 'languageDirection')
148
+ }
149
+
150
+ get languagePhraseSource() {
151
+ return this._helper_get(this._langData, 'languagePhraseSource')
152
+ }
153
+
103
154
  // Status
104
155
 
105
156
  get isFullscreen() {
@@ -179,6 +230,11 @@ class RemoteCalibrator {
179
230
  return this._helper_get(this._environmentData, 'fullDescription')
180
231
  }
181
232
 
233
+ get userLanguage() {
234
+ if (!this._environmentData.length) this.environment()
235
+ return this._helper_get(this._environmentData, 'userLanguage')
236
+ }
237
+
182
238
  // Screen
183
239
 
184
240
  get displayWidthPx() {
@@ -283,6 +339,10 @@ class RemoteCalibrator {
283
339
  return this._environmentData
284
340
  }
285
341
 
342
+ get languageData() {
343
+ return this._langData
344
+ }
345
+
286
346
  /* --------------------------------- SETTERS -------------------------------- */
287
347
 
288
348
  /**
@@ -347,6 +407,13 @@ class RemoteCalibrator {
347
407
  set newFullscreenData(data) {
348
408
  this._fullscreenData.push(data)
349
409
  }
410
+
411
+ /**
412
+ * @param {{ value: { language: string; languageNameEnglish: string; languageNameNative: string; languageDirection: string; languagePhraseSource: string; }; timestamp: Date; }} data
413
+ */
414
+ set newLanguageData(data) {
415
+ this._langData.push(data)
416
+ }
350
417
  }
351
418
 
352
419
  /**
@@ -360,6 +427,7 @@ RemoteCalibrator.prototype.init = function (options = {}, callback) {
360
427
  options = Object.assign(
361
428
  {
362
429
  id: randomPhrases(),
430
+ language: 'AUTO',
363
431
  fullscreen: false,
364
432
  },
365
433
  options
@@ -374,6 +442,12 @@ RemoteCalibrator.prototype.init = function (options = {}, callback) {
374
442
 
375
443
  this.environment()
376
444
 
445
+ if (this._CONST.S.AUTO === options.language)
446
+ // AUTO
447
+ this.newLanguageData = looseSetLanguage(this.userLanguage.value)
448
+ else this.newLanguageData = looseSetLanguage(options.language)
449
+ this._lang = this.language.value
450
+
377
451
  if (callback && typeof callback === 'function') callback(this._id)
378
452
  }
379
453
  }
@@ -390,9 +464,18 @@ RemoteCalibrator.prototype.environment = function (callback) {
390
464
  const device = this.deviceDetector.parse(platform.ua)
391
465
  const bot = device.bot
392
466
 
467
+ if (!device.device)
468
+ device.device = {
469
+ type: null,
470
+ model: null,
471
+ brand: null,
472
+ }
473
+
393
474
  const data = {
394
475
  value: {
395
- bot: bot ? `${bot.name} (${bot.category}) by ${bot.producer.name}` : '',
476
+ bot: bot
477
+ ? `${bot.name} (${bot.category}) by ${bot.producer.name}`
478
+ : null,
396
479
  browser: platform.name,
397
480
  browserVersion: platform.version,
398
481
  deviceType: device.device.type,
@@ -403,6 +486,8 @@ RemoteCalibrator.prototype.environment = function (callback) {
403
486
  systemFamily: platform.os.family,
404
487
  description: platform.description,
405
488
  fullDescription: platform.ua,
489
+ userLanguage:
490
+ window.navigator.userLanguage || window.navigator.language,
406
491
  },
407
492
  timestamp: this.id.timestamp,
408
493
  }
@@ -438,6 +523,10 @@ RemoteCalibrator.prototype.getFullscreen = function (f = true) {
438
523
 
439
524
  if (f && !debug) getFullscreen()
440
525
 
526
+ // Minimize address bar on mobile devices
527
+ // ! Experimental
528
+ if (this.isMobile.value) window.scrollBy(0, 1)
529
+
441
530
  this.newFullscreenData = {
442
531
  value: f && !debug,
443
532
  timestamp: new Date(),
@@ -446,6 +535,18 @@ RemoteCalibrator.prototype.getFullscreen = function (f = true) {
446
535
  return f && !debug
447
536
  }
448
537
 
538
+ /**
539
+ * Set a new language
540
+ */
541
+ RemoteCalibrator.prototype.newLanguage = function (lang) {
542
+ if (this.checkInitialized()) {
543
+ let data
544
+ this.newLanguageData = data = looseSetLanguage(lang)
545
+ this._lang = this.language.value
546
+ return data
547
+ }
548
+ }
549
+
449
550
  /**
450
551
  *
451
552
  * Add background
@@ -458,6 +559,7 @@ RemoteCalibrator.prototype._addBackground = function (inner) {
458
559
  if (!b) {
459
560
  b = document.createElement('div')
460
561
  b.id = 'calibration-background'
562
+ b.className = 'calibration-background' + ` rc-lang-${this.LD.toLowerCase()}`
461
563
 
462
564
  document.body.classList.add('lock-view')
463
565
  document.body.appendChild(b)
@@ -8,15 +8,31 @@
8
8
  .rc-button {
9
9
  text-align: center;
10
10
  border: none !important;
11
- background: #ffffffee;
12
11
  line-height: 150% !important;
13
12
  font-size: 1rem !important;
14
13
  font-weight: 700 !important;
15
- color: #333;
16
14
  padding: 1rem 1.5rem !important;
17
15
  margin: 0.25rem !important;
18
16
  border-radius: 7px !important;
19
17
  cursor: pointer;
18
+ }
19
+
20
+ .rc-go-button {
21
+ background: #ff9a00aa;
22
+ color: #fff;
23
+
24
+ &:hover {
25
+ background: #ff9a00;
26
+ }
27
+
28
+ &:active {
29
+ background: #d68200;
30
+ }
31
+ }
32
+
33
+ .rc-cancel-button {
34
+ background: #ffffffee;
35
+ color: #333;
20
36
 
21
37
  &:hover {
22
38
  background: #ddd;
@@ -3,17 +3,22 @@
3
3
  }
4
4
 
5
5
  #blind-spot-canvas {
6
- z-index: -1;
6
+ position: fixed;
7
7
  display: block;
8
- position: absolute;
8
+ z-index: -1;
9
9
  top: 0;
10
10
  left: 0;
11
+ bottom: 0;
12
+ right: 0;
13
+ padding: 0;
14
+ margin: 0;
11
15
  }
12
16
 
13
- #blind-spot-instruction {
14
- display: block !important;
15
- top: 65%;
16
- }
17
+ // #blind-spot-instruction {
18
+ // display: block !important;
19
+ // top: 65%;
20
+ // position: fixed;
21
+ // }
17
22
 
18
23
  #pip-video {
19
24
  display: none;
@@ -31,7 +36,7 @@
31
36
  /* ----------------------------------- PD ----------------------------------- */
32
37
 
33
38
  #rc-ruler {
34
- position: absolute;
39
+ position: fixed;
35
40
  max-height: 120px;
36
41
  overflow: hidden;
37
42
  }
package/src/css/main.css CHANGED
@@ -28,10 +28,13 @@
28
28
 
29
29
  .calibration-instruction {
30
30
  position: absolute;
31
- text-align: left;
32
31
  user-select: none;
33
32
  }
34
33
 
34
+ .calibration-instruction-scrollable {
35
+ height: 200%;
36
+ }
37
+
35
38
  .calibration-instruction h1 {
36
39
  min-width: 360px;
37
40
  font-weight: 700;
@@ -106,7 +109,7 @@
106
109
  }
107
110
 
108
111
  .float-instruction {
109
- position: absolute;
112
+ position: fixed;
110
113
  text-align: center;
111
114
  user-select: none;
112
115
  background: rgba(255, 255, 255, 0.9);
@@ -132,12 +135,11 @@
132
135
  position: fixed !important;
133
136
  width: 100% !important;
134
137
  bottom: 3px !important;
135
- left: 50% !important;
136
- transform: translate(-50%, 0) !important;
137
138
  color: #999 !important;
138
139
  margin: 0 !important;
139
140
  padding: 0 !important;
140
141
  line-height: 100% !important;
142
+ text-align: center !important;
141
143
  }
142
144
 
143
145
  /* -------------------------------------------------------------------------- */
@@ -145,3 +147,15 @@
145
147
  .lock-view {
146
148
  overflow: hidden !important;
147
149
  }
150
+
151
+ /* -------------------------------------------------------------------------- */
152
+
153
+ .rc-lang-ltr {
154
+ direction: ltr !important;
155
+ text-align: left !important;
156
+ }
157
+
158
+ .rc-lang-rtl {
159
+ direction: rtl !important;
160
+ text-align: right !important;
161
+ }
@@ -17,7 +17,6 @@
17
17
  border-radius: 10px !important;
18
18
  box-shadow: var(--rc-panel-darken-color-semi) 0px 50px 100px -20px,
19
19
  var(--rc-panel-theme-color-semi) 0px 30px 60px -30px !important;
20
- text-align: left !important;
21
20
 
22
21
  * {
23
22
  outline: none;
@@ -34,7 +33,7 @@
34
33
 
35
34
  .rc-panel-title {
36
35
  color: #fff !important;
37
- margin: 1rem auto 0 1rem !important;
36
+ margin: 1rem 1rem 0 1rem !important;
38
37
  font-size: 2rem !important;
39
38
  font-weight: 600 !important;
40
39
  }
@@ -100,10 +99,6 @@
100
99
  &.rc-panel-steps-s {
101
100
  flex-flow: column nowrap;
102
101
 
103
- .rc-panel-step {
104
- text-align: left;
105
- }
106
-
107
102
  .rc-panel-step-name {
108
103
  margin: 1.2rem 1.5rem !important;
109
104
  }
@@ -1,41 +1,43 @@
1
- .slider {
1
+ .rc-slider {
2
2
  position: absolute;
3
3
  display: block;
4
4
  -webkit-appearance: none;
5
5
  appearance: none;
6
6
  width: calc(100% - 4rem);
7
- height: 30px;
8
- background: #fff;
9
- opacity: 0.7;
7
+ height: 10px;
8
+ background: linear-gradient(90deg, #ffc772, #ffc772 60%, #fff 60%);
9
+ opacity: 0.8;
10
10
  /* top: max(45%, 200px); */
11
11
  left: 2rem;
12
- border-radius: 15px;
12
+ border-radius: 5px;
13
13
  z-index: 1;
14
14
  cursor: grab;
15
15
  -webkit-transition: opacity 0.3s;
16
16
  transition: opacity 0.3s;
17
+ direction: ltr !important;
17
18
  }
18
19
 
19
- .slider:hover {
20
+ .rc-slider:hover {
20
21
  opacity: 0.99;
21
22
  }
22
23
 
23
- .slider::-webkit-slider-thumb {
24
+ .rc-slider::-webkit-slider-thumb {
24
25
  -webkit-appearance: none;
25
26
  appearance: none;
26
27
  width: 30px;
27
28
  height: 30px;
28
29
  border-radius: 15px;
29
- background: #666;
30
+ background: #ff9a00;
31
+ box-shadow: 0 0 12px 0 #88520033;
30
32
  cursor: inherit;
31
33
  }
32
34
 
33
- .slider::-moz-range-thumb,
34
- .slider::-ms-thumb {
35
- width: 20px;
35
+ .rc-slider::-moz-range-thumb,
36
+ .rc-slider::-ms-thumb {
37
+ width: 30px;
36
38
  height: 30px;
37
39
  border-radius: 15px;
38
- background: #666;
40
+ background: #ff9a00;
39
41
  cursor: inherit;
40
42
  }
41
43
 
@@ -55,21 +57,22 @@
55
57
  #size-arrow {
56
58
  position: absolute;
57
59
  display: block;
60
+ /* display: none; */
58
61
  width: 70px;
59
62
  height: auto;
60
63
  z-index: 3;
61
64
  }
62
65
 
63
66
  #size-arrow-fill {
64
- transition: fill 0.1s;
67
+ transition: fill 0.3s;
65
68
  }
66
69
 
67
70
  .minor {
68
- transition: opacity 0.1s;
71
+ transition: opacity 0.25s;
69
72
  }
70
73
 
71
- .slider:hover ~ .size-obj .minor,
72
- .slider:active ~ .size-obj .minor {
74
+ /* .rc-slider:hover ~ .size-obj .minor, */
75
+ .rc-slider:active ~ .size-obj .minor {
73
76
  opacity: 0;
74
77
  }
75
78
 
package/src/css/swal.css CHANGED
@@ -25,7 +25,6 @@
25
25
  line-height: 150% !important;
26
26
  font-weight: normal !important;
27
27
  user-select: none !important;
28
- text-align: left !important;
29
28
  }
30
29
 
31
30
  .animate__animated.animate__fadeInUp,
@@ -1,5 +1,5 @@
1
1
  import RemoteCalibrator from './core'
2
- import { blurAll } from './helpers'
2
+ import { blurAll } from './components/utils'
3
3
 
4
4
  /**
5
5
  *