Skip to content

Commit

Permalink
Merge pull request #280 from lightning-js/dev
Browse files Browse the repository at this point in the history
Release 1.19.0
  • Loading branch information
michielvandergeest authored Jan 31, 2025
2 parents d7bdee2 + b85c703 commit d967628
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 24 deletions.
1 change: 1 addition & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ module.exports = {
parser: 'babel-eslint',
ecmaVersion: 2018,
sourceType: 'module',
requireConfigFile: false,
babelOptions: {
plugins: ['@babel/plugin-syntax-import-assertions'],
},
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## v1.19.0

- Fixed `show`-attribute when an `alpha`-attribute is also present
- Added `inspector-data`-attribute to help with automated testing based on the Lightning inspector
- Added reactivity to Route changes (`this.$router.state.path` and `this.$router.state.navigating`)
- Added `renderQuality` launch setting

## v1.18.1

_27 jan 2025_
Expand Down
32 changes: 32 additions & 0 deletions docs/router/basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,35 @@ The Router API provides several useful methods and properties for managing route
- `this.$router.currentRoute` - retrieve the current route
- `this.$router.routes` - retrieve the list of all routes
- `this.$router.navigating` - retrieve the current navigating state
- `this.$router.state` - reactive router state (see below)

### Reactive router state

The reactive router state (`this.$router.state`) can be useful in situations where you want to hook up reactive changes in your App to Route changes.

The `state` variable on the `this.$router` object returns a reactive object with 2 keys: `path` and `navigating`. The values of these keys will automaticaly update when the router navigates from one page to another.

The router state changes can be used in a Blits template, they can be _watched_ and they can be used in generic busines logic, as demonstrated in the example below.

```js
export default Blits.Component('MyComponent', {
template: `
<Element w="1920" h="1080">
<!-- dynamically display the current path -->
<Text x="100" h="100" :content="$$router.state.path" />
<!-- show loading text when router is navigating -->
<Text :show="$showLoader">Loading ...</Text>
</Element>
`,
watch: {
'$router.state.path'(v, old) {
Log.info(`Router Path changed from ${old} to ${v}`)
}
},
computed: {
showLoader() {
return this.$router.state.navigating
}
}
})
```
48 changes: 47 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,30 @@ declare module '@lightningjs/blits' {
*/
readonly navigating: boolean;

/**
* Reactive router state
*/
state: {
/**
* Path of the current route
*
* Can be used in:
* - a template as `$$router.state.path`
* - inside business logic as `this.$router.state.path`
* - as a watcher as `$router.state.path(v) {}`
*/
readonly path: string
/**
* Whether or not the router is currently in the process of navigating
* between pages
*
* Can be used in:
* - a template as `$$router.state.navihating`
* - inside business logic as `this.$router.state.navigating`
* - as a watcher as `$router.state.navigating(v) {}`
*/
readonly navigating: boolean
}
}

export type ComponentBase = {
Expand Down Expand Up @@ -599,6 +623,7 @@ declare module '@lightningjs/blits' {
}

type ScreenResolutions = 'hd' | '720p' | 720 | 'fhd' | 'fullhd' | '1080p' | 1080 | '4k' | '2160p' | 2160
type RenderQualities = 'low' | 'medium' | 'high' | 'retina' | number

type ReactivityModes = 'Proxy' | 'defineProperty'
type RenderModes = 'webgl' | 'canvas'
Expand Down Expand Up @@ -667,7 +692,7 @@ declare module '@lightningjs/blits' {
*
* Currently 3 screen resolutions are supported, which can be defined with different alias values:
*
* For 720x1080 (1px = 0.66666667px)
* For 720x1280 (1px = 0.66666667px)
* - hd
* - 720p
* - 720
Expand All @@ -685,6 +710,27 @@ declare module '@lightningjs/blits' {
*/
screenResolution?: ScreenResolutions,
/**
* Controls the quality of the rendered App.
*
* Setting a lower quality leads to less detail on screen, but can positively affect overall
* performance and smoothness of the App (i.e. a higher FPS).
*
* The render quality can be one of the following presets:
*
* - `low` => 66% quality
* - `medium` => 85% quality
* - `high` => 100% quality
* - `retina` => 200% quality
*
* It's also possible to provide a custom value as a (decimal) number:
*
* - `0.2` => 20% quality
* - `1.5` => 150% quality
*
* Defaults to 1 (high quality) when not specified
*/
renderQuality?: RenderQualities,
/**
* Custom pixel ratio of the device used to convert dimensions
* and positions in the App code to the actual device logical coordinates
*
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lightningjs/blits",
"version": "1.18.1",
"version": "1.19.0",
"description": "Blits: The Lightning 3 App Development Framework",
"bin": "bin/index.js",
"exports": {
Expand Down
5 changes: 3 additions & 2 deletions src/component/base/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/

import symbols from '../../lib/symbols.js'
import { to, currentRoute, navigating, back } from '../../router/router.js'
import { to, currentRoute, back, state } from '../../router/router.js'

export default {
$router: {
Expand All @@ -30,8 +30,9 @@ export default {
return this[symbols.routes]
},
get navigating() {
return navigating
return state.navigating
},
state,
},
writable: false,
enumerable: true,
Expand Down
7 changes: 7 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,10 @@ export const SCREEN_RESOLUTIONS = {
'2160p': 2,
2160: 2,
}

export const RENDER_QUALITIES = {
low: 0.66666667,
medium: 0.85,
high: 1,
retina: 2,
}
11 changes: 9 additions & 2 deletions src/engines/L3/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ const propsTransformer = {
},
set show(v) {
if (v) {
this.props['alpha'] = 1
this.props['alpha'] = this.raw['alpha'] !== undefined ? this.raw['alpha'] : 1
this.props['width'] = this.raw['w'] || this.raw['width'] || 0
this.props['height'] = this.raw['h'] || this.raw['height'] || 0
} else {
Expand All @@ -309,7 +309,9 @@ const propsTransformer = {
}
},
set alpha(v) {
this.props['alpha'] = v
if(this.raw['show'] === undefined || this.raw['show'] === true) {
this.props['alpha'] = v
}
},
set shader(v) {
if (v !== null) {
Expand Down Expand Up @@ -419,6 +421,11 @@ const propsTransformer = {
this.props['mountY'] = 1
}
},
set 'inspector-data'(v) {
if (typeof v === 'object' || (isObjectString(v) === true && (v = parseToObject(v)))) {
this.props['data'] = v
}
},
}

const Element = {
Expand Down
8 changes: 6 additions & 2 deletions src/engines/L3/launch.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { CanvasCoreRenderer, CanvasTextRenderer } from '@lightningjs/renderer/ca
import { Inspector } from '@lightningjs/renderer/inspector'

import { Log } from '../../lib/log.js'
import { SCREEN_RESOLUTIONS } from '../../constants.js'
import { SCREEN_RESOLUTIONS, RENDER_QUALITIES } from '../../constants.js'
import colors from '../../lib/colors/colors.js'
import fontLoader from './fontLoader.js'
import shaderLoader from './shaderLoader.js'
Expand All @@ -43,11 +43,15 @@ const textRenderEngines = (settings) => {
}

export default (App, target, settings = {}) => {
console.log(RENDER_QUALITIES[settings.renderQuality] || settings.renderQuality || 1)

renderer = new RendererMain(
{
appWidth: settings.w || 1920,
appHeight: settings.h || 1080,
fpsUpdateInterval: settings.fpsInterval || 1000,
devicePhysicalPixelRatio:
RENDER_QUALITIES[settings.renderQuality] || settings.renderQuality || 1,
deviceLogicalPixelRatio:
settings.pixelRatio ||
SCREEN_RESOLUTIONS[settings.screenResolution] ||
Expand All @@ -66,7 +70,7 @@ export default (App, target, settings = {}) => {
renderEngine: renderEngine(settings),
fontEngines: textRenderEngines(settings),
canvas: settings.canvas,
textureProcessingTimeLimit: settings.textureProcessingTimeLimit
textureProcessingTimeLimit: settings.textureProcessingTimeLimit,
},
target
)
Expand Down
4 changes: 2 additions & 2 deletions src/focus.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/

import symbols from './lib/symbols.js'
import { navigating } from './router/router.js'
import { state } from './router/router.js'
import Settings from './settings.js'
import { DEFAULT_HOLD_TIMEOUT_MS } from './constants.js'

Expand Down Expand Up @@ -58,7 +58,7 @@ export default {
}
},
input(key, event) {
if (navigating === true) return
if (state.navigating === true) return
focusChain = walkChain([focusedComponent], key)
const componentWithInputEvent = focusChain.shift()

Expand Down
8 changes: 6 additions & 2 deletions src/lib/reactivity/reactive.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,14 @@ const reactiveProxy = (original, _parent = null, _key, global) => {
: oldRawValue === rawValue

if (isEqual === false) {
if(typeof value === 'object') {
if (typeof value === 'object') {
if (Array.isArray(value) === true) {
value = getRaw(value).slice(0)
} else if(target[key] !== null && target[key] !== undefined && Object.getPrototypeOf(value) === Object.prototype) {
} else if (
target[key] !== null &&
target[key] !== undefined &&
Object.getPrototypeOf(value) === Object.prototype
) {
value = Object.assign(receiver[key], value)
}
}
Expand Down
23 changes: 13 additions & 10 deletions src/router/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

import { default as fadeInFadeOutTransition } from './transitions/fadeInOut.js'
import { reactive } from '../lib/reactivity/reactive.js'

import symbols from '../lib/symbols.js'
import { Log } from '../lib/log.js'
Expand All @@ -24,7 +25,7 @@ import Focus from '../focus.js'
import Announcer from '../announcer/announcer.js'

export let currentRoute
export let navigating = false
export const state = reactive({ path: null, navigating: false })

const cacheMap = new WeakMap()
const history = []
Expand Down Expand Up @@ -114,7 +115,7 @@ export const matchHash = (path, routes = []) => {
}

export const navigate = async function () {
navigating = true
state.navigating = true
if (this.parent[symbols.routes]) {
const previousRoute = currentRoute
const { hash, queryParams } = getHash()
Expand Down Expand Up @@ -237,6 +238,8 @@ export const navigate = async function () {
}
}

state.path = route.path

// apply in transition
if (route.transition.in) {
if (Array.isArray(route.transition.in)) {
Expand Down Expand Up @@ -268,7 +271,7 @@ export const navigate = async function () {

// reset navigating indicators
navigatingBack = false
navigating = false
state.navigating = false
}

const removeView = async (route, view, transition) => {
Expand Down Expand Up @@ -320,7 +323,7 @@ export const to = (location, data = {}, options = {}) => {
window.location.hash = `#${location}`
}

export const back = function(){
export const back = function () {
const route = history.pop()
if (route && currentRoute !== route) {
// set indicator that we are navigating back (to prevent adding page to history stack)
Expand All @@ -335,11 +338,11 @@ export const back = function(){
return true
}

const backtrack = currentRoute && currentRoute.options.backtrack || false
const backtrack = (currentRoute && currentRoute.options.backtrack) || false

// If we deeplink to a page without backtrack
// we we let the RouterView handle back
if(!backtrack){
if (backtrack === false) {
return false
}

Expand All @@ -348,19 +351,19 @@ export const back = function(){
let level = path.split('/').length

// On root return
if(level <= 1){
if (level <= 1) {
return false
}

while(level--){
if(!hashEnd.test(path)){
while (level--) {
if (!hashEnd.test(path)) {
return false
}
// Construct new path to backtrack to
path = path.replace(hashEnd, '')
const route = matchHash(path, this.parent[symbols.routes])

if(route && backtrack){
if (route && backtrack) {
to(route.path)
return true
}
Expand Down

0 comments on commit d967628

Please sign in to comment.