@lightningjs/blits 1.17.1 → 1.18.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.18.1
4
+
5
+ _27 jan 2025_
6
+
7
+ - Fixed issue with navigating back to a router page with `keepalive=true`
8
+
9
+ ## v1.18.0
10
+
11
+ _27 jan 2025_
12
+
13
+ - Added backtracking functionality to the Router
14
+ - Upgraded to latest version of the renderer (2.10.0)
15
+ - Changed setting `textureProcessingLimit` to `textureProcessingTimeLimit`
16
+
17
+
3
18
  ## v1.17.1
4
19
 
5
20
  _24 jan 2025_
@@ -96,6 +96,42 @@ export default Blits.Component('Poster', {
96
96
 
97
97
  Whenever you navigate to a new page, the URL hash will automatically be updated. Unless specified otherwise, navigating to a new page, will add that route to the history stack. The `back` input action is automatically wired up to navigate back down the history stack.
98
98
 
99
+ ## Deeplinking
100
+
101
+ The Router plugin has support for deeplinking. When the App is loaded with a URL hash (i.e. `#/pages/settings/network`), the router will try to match that hash to a defined route. This means that your app can be deep linked into, by simply providing the correct URL hash.
102
+
103
+ This is an important feature for several reasons:
104
+
105
+ - It will allow external sources (like operators and UIs) to link directly to a specific page in your app (i.e. the details page of a specific movie)
106
+ - If dynamic routes are used, the App only loads what is needed, to keep memory usage low and the initial load time fast
107
+ - Data provided in the URL hash can still be used to set the initial state of the App
108
+
109
+ ## Backtracking
110
+
111
+ When a user enters your App via a deeplink, there is technically no history available. By default, this means that a Back keypress goes straight to
112
+ the App's `root`-route (i.e. the `Blits.Application()`-component).
113
+
114
+ In some cases, you may want walk back down the logical path of the deeplinked page instead, and navigate to the first existing parent route (i.e. go from `/movies/comedy/american-pie` to `/movies/comedy`).
115
+
116
+ By setting the route option `backtrack` to `true` in the route definition (or in the `this.$router.to()`-method), the router will recursively remove the last part of the route hash, until it finds a valid path to navigate to.
117
+
118
+ ```js
119
+ {
120
+ path: '/examples/router-hooks/episode/:id',
121
+ component: Episode,
122
+ transition: PageTransitions.slideInOutUp,
123
+ options: {
124
+ backtrack: true,
125
+ },
126
+ },
127
+ {
128
+ path: '/examples/router-hooks/episode',
129
+ component: EpisodesOverview,
130
+ },
131
+ ```
132
+
133
+ In the example above, the `backtrack` option is set to `true` for the `/examples/router-hooks/episode/:id` route. When the user navigates to `/examples/router-hooks/episode/1`, the `back` input action will navigate to `/examples/router-hooks/episode` instead of exiting the App.
134
+
99
135
  ## Router API
100
136
 
101
137
  The Router API provides several useful methods and properties for managing routes and navigation:
package/index.d.ts CHANGED
@@ -783,12 +783,13 @@ declare module '@lightningjs/blits' {
783
783
  */
784
784
  canvas?: HTMLCanvasElement,
785
785
  /**
786
- * The maximum number of textures to process in a single frame. This is used to
787
- * prevent the renderer from processing too many textures in a single frame.
786
+ * The maximum amount of time the renderer is allowed to process textures in a
787
+ * single frame. If the processing time exceeds this limit, the renderer will
788
+ * skip processing the remaining textures and continue rendering the frame.
788
789
  *
789
- * Defaults to `0` (meaning no limit)
790
+ * Defaults to `10`
790
791
  */
791
- textureProcessingLimit?: number
792
+ textureProcessingTimeLimit?: number
792
793
  }
793
794
 
794
795
  interface State {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightningjs/blits",
3
- "version": "1.17.1",
3
+ "version": "1.18.1",
4
4
  "description": "Blits: The Lightning 3 App Development Framework",
5
5
  "bin": "bin/index.js",
6
6
  "exports": {
@@ -52,7 +52,7 @@
52
52
  },
53
53
  "dependencies": {
54
54
  "@lightningjs/msdf-generator": "^1.1.1",
55
- "@lightningjs/renderer": "^2.9.1"
55
+ "@lightningjs/renderer": "^2.10.0"
56
56
  },
57
57
  "repository": {
58
58
  "type": "git",
@@ -18,7 +18,7 @@
18
18
  import Component from '../component.js'
19
19
  import Router from '../router/router.js'
20
20
 
21
- let handler
21
+ let hashchangeHandler = null
22
22
 
23
23
  export default () =>
24
24
  Component('RouterView', {
@@ -53,12 +53,13 @@ return elms
53
53
  },
54
54
  hooks: {
55
55
  ready() {
56
- handler = () => Router.navigate.apply(this)
56
+ hashchangeHandler = () => Router.navigate.apply(this)
57
57
  Router.navigate.apply(this)
58
- window.addEventListener('hashchange', handler)
58
+ window.addEventListener('hashchange', hashchangeHandler)
59
+
59
60
  },
60
61
  destroy() {
61
- window.removeEventListener('hashchange', handler, false)
62
+ window.removeEventListener('hashchange', hashchangeHandler, false)
62
63
  },
63
64
  focus() {
64
65
  this.activeView && this.activeView.$focus()
@@ -66,7 +67,7 @@ return elms
66
67
  },
67
68
  input: {
68
69
  back(e) {
69
- const navigating = Router.back()
70
+ const navigating = Router.back.call(this)
70
71
  if (navigating === false) {
71
72
  this.parent.$focus(e)
72
73
  }
@@ -18,7 +18,7 @@
18
18
  import Component from '../component.js'
19
19
  import Router from '../router/router.js'
20
20
 
21
- let handler
21
+ let hashchangeHandler = null
22
22
 
23
23
  export default () =>
24
24
  Component('RouterView', {
@@ -32,12 +32,13 @@ export default () =>
32
32
  },
33
33
  hooks: {
34
34
  ready() {
35
- handler = () => Router.navigate.apply(this)
35
+ hashchangeHandler = () => Router.navigate.apply(this)
36
36
  Router.navigate.apply(this)
37
- window.addEventListener('hashchange', handler)
37
+ window.addEventListener('hashchange', hashchangeHandler)
38
+
38
39
  },
39
40
  destroy() {
40
- window.removeEventListener('hashchange', handler, false)
41
+ window.removeEventListener('hashchange', hashchangeHandler, false)
41
42
  },
42
43
  focus() {
43
44
  this.activeView && this.activeView.$focus()
@@ -45,7 +46,7 @@ export default () =>
45
46
  },
46
47
  input: {
47
48
  back(e) {
48
- const navigating = Router.back()
49
+ const navigating = Router.back.call(this)
49
50
  if (navigating === false) {
50
51
  this.parent.$focus(e)
51
52
  }
@@ -66,7 +66,7 @@ export default (App, target, settings = {}) => {
66
66
  renderEngine: renderEngine(settings),
67
67
  fontEngines: textRenderEngines(settings),
68
68
  canvas: settings.canvas,
69
- textureProcessingLimit: settings.textureProcessingLimit
69
+ textureProcessingTimeLimit: settings.textureProcessingTimeLimit
70
70
  },
71
71
  target
72
72
  )
@@ -107,14 +107,12 @@ const reactiveProxy = (original, _parent = null, _key, global) => {
107
107
  : oldRawValue === rawValue
108
108
 
109
109
  if (isEqual === false) {
110
- if (Array.isArray(value) === true) {
111
- value = getRaw(value).slice(0)
112
- } else if (
113
- typeof value === 'object' &&
114
- target[key] !== null &&
115
- Array.isArray(target) === false
116
- ) {
117
- value = Object.assign(receiver[key], value)
110
+ if(typeof value === 'object') {
111
+ if (Array.isArray(value) === true) {
112
+ value = getRaw(value).slice(0)
113
+ } else if(target[key] !== null && target[key] !== undefined && Object.getPrototypeOf(value) === Object.prototype) {
114
+ value = Object.assign(receiver[key], value)
115
+ }
118
116
  }
119
117
  result = Reflect.set(target, key, value, receiver)
120
118
  }
@@ -320,9 +320,9 @@ export const to = (location, data = {}, options = {}) => {
320
320
  window.location.hash = `#${location}`
321
321
  }
322
322
 
323
- export const back = () => {
323
+ export const back = function(){
324
324
  const route = history.pop()
325
- if (route) {
325
+ if (route && currentRoute !== route) {
326
326
  // set indicator that we are navigating back (to prevent adding page to history stack)
327
327
  navigatingBack = true
328
328
  let targetRoutePath = route.path
@@ -333,9 +333,40 @@ export const back = () => {
333
333
  }
334
334
  to(targetRoutePath)
335
335
  return true
336
- } else {
336
+ }
337
+
338
+ const backtrack = currentRoute && currentRoute.options.backtrack || false
339
+
340
+ // If we deeplink to a page without backtrack
341
+ // we we let the RouterView handle back
342
+ if(!backtrack){
343
+ return false
344
+ }
345
+
346
+ const hashEnd = /(\/:?[\w%\s-]+)$/
347
+ let path = currentRoute.path
348
+ let level = path.split('/').length
349
+
350
+ // On root return
351
+ if(level <= 1){
337
352
  return false
338
353
  }
354
+
355
+ while(level--){
356
+ if(!hashEnd.test(path)){
357
+ return false
358
+ }
359
+ // Construct new path to backtrack to
360
+ path = path.replace(hashEnd, '')
361
+ const route = matchHash(path, this.parent[symbols.routes])
362
+
363
+ if(route && backtrack){
364
+ to(route.path)
365
+ return true
366
+ }
367
+ }
368
+
369
+ return false
339
370
  }
340
371
 
341
372
  export default {