From 14eae0fa9be63e4bb226cf7b23b1651da3b74cc2 Mon Sep 17 00:00:00 2001 From: Aleksi Lassila Date: Wed, 24 Jan 2024 01:00:12 +0200 Subject: [PATCH] Add Tizen 5.5 Polyfills, implement dpad navigation with specified components --- .idea/reiverr.iml | 2 + package.json | 10 + src/App.svelte | 74 ++++--- src/Container.svelte | 28 +++ src/FocusableButton.svelte | 20 ++ src/TestElement.svelte | 22 ++ src/lib/actions/focusAction.ts | 189 +++++++++++++----- src/lib/components-new/NavbarItem.svelte | 33 ++- .../Carousel/CarouselPlaceholderItems.svelte | 28 +-- src/lib/components/Selectable.svelte | 4 +- src/lib/pages/LibraryPage.svelte | 19 +- src/lib/pages/ManagePage.svelte | 7 +- src/lib/pages/MoviesPage.svelte | 7 +- src/lib/pages/SearchPage.svelte | 7 +- src/lib/pages/SeriesPage.svelte | 7 +- vite.config.ts | 12 +- 16 files changed, 322 insertions(+), 147 deletions(-) create mode 100644 src/Container.svelte create mode 100644 src/FocusableButton.svelte create mode 100644 src/TestElement.svelte diff --git a/.idea/reiverr.iml b/.idea/reiverr.iml index c681724..fe7ecd0 100644 --- a/.idea/reiverr.iml +++ b/.idea/reiverr.iml @@ -7,6 +7,8 @@ + + diff --git a/package.json b/package.json index 638c23c..7e59fe1 100644 --- a/package.json +++ b/package.json @@ -55,5 +55,15 @@ "typescript": "^5.2.2", "vite": "^4.5.1", "vite-plugin-singlefile": "^0.13.5" + }, + "browserslist": { + "production": [ + "supports es6-module" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] } } diff --git a/src/App.svelte b/src/App.svelte index 6c4e240..e6b1bc6 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -1,34 +1,54 @@ -
+ + + + + + + + + + + + + - + -
+ - + - + - + - + - + -
+ -
+ diff --git a/src/Container.svelte b/src/Container.svelte new file mode 100644 index 0000000..681e580 --- /dev/null +++ b/src/Container.svelte @@ -0,0 +1,28 @@ + + + + + diff --git a/src/FocusableButton.svelte b/src/FocusableButton.svelte new file mode 100644 index 0000000..2b0b14a --- /dev/null +++ b/src/FocusableButton.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/TestElement.svelte b/src/TestElement.svelte new file mode 100644 index 0000000..51c65de --- /dev/null +++ b/src/TestElement.svelte @@ -0,0 +1,22 @@ + + + +

+ Hello world! +

+
diff --git a/src/lib/actions/focusAction.ts b/src/lib/actions/focusAction.ts index 161e69b..ce2da32 100644 --- a/src/lib/actions/focusAction.ts +++ b/src/lib/actions/focusAction.ts @@ -1,5 +1,4 @@ import { derived, get, type Readable, type Writable, writable } from 'svelte/store'; -import { navigate } from 'svelte-navigator'; export type Registerer = (htmlElement: HTMLElement) => { destroy: () => void }; @@ -19,6 +18,7 @@ export class Container { right: undefined }; private focusByDefault: boolean = false; + private isInitialized: boolean = false; private direction: FlowDirection = 'vertical'; @@ -42,12 +42,13 @@ export class Container { return false; }); - static objects = new Map(); + static objects = new Map(); constructor(name: string = '') { this.id = Symbol(); this.name = name; - Container.objects.set(this.id, this); + + // Find parents } setDirection(direction: FlowDirection) { @@ -60,12 +61,18 @@ export class Container { return this; } - createChild(name: string = '') { - const child = new Container(name); - this.addChild(child); - return child; + setHtmlElement(htmlElement: HTMLElement) { + this.htmlElement = htmlElement; + Container.objects.set(htmlElement, this); + return this; } + // createChild(htmlElement: HTMLElement, name: string = '') { + // const child = new Container(htmlElement, name); + // this.addChild(child); + // return child; + // } + focus() { if (this.children.length > 0) { this.children[get(this.focusIndex)]?.focus(); @@ -89,7 +96,7 @@ export class Container { isFocusable() { if (this.htmlElement) { - return true; + return this.htmlElement.tabIndex >= 0; } else { for (const child of this.children) { if (child.isFocusable()) { @@ -143,57 +150,135 @@ export class Container { } } - getChildRegisterer(): Registerer { - return (htmlElement: HTMLElement) => { - if (this.htmlElement) console.warn('Registering to a container that has an element.'); + // getChildRegisterer(): Registerer { + // return (htmlElement: HTMLElement) => { + // if (this.htmlElement) console.warn('Registering to a container that has an element.'); + // + // this.createChild().addHtmlElement(htmlElement); + // + // if (!get(Container.focusedObject) && this.shouldFocusByDefault()) { + // this.focus(); + // } + // + // return { + // destroy: () => { + // this.removeHtmlElement(); + // } + // }; + // }; + // } + // + // getHtmlElementRegisterer(): Registerer { + // return (htmlElement: HTMLElement) => { + // if (this.children.length > 0) { + // console.warn('Registering an html element to a container that has children.'); + // for (const child of this.children) { + // this.removeChild(child); + // } + // } + // this.addHtmlElement(htmlElement); + // return { + // destroy: () => { + // this.removeHtmlElement(); + // } + // }; + // }; + // } - this.createChild().addHtmlElement(htmlElement); + _initializeContainer() { + const getParentContainer = (htmlElement: HTMLElement): Container | undefined => { + if (Container.objects.get(htmlElement)) return Container.objects.get(htmlElement); + else if (htmlElement.parentElement) return getParentContainer(htmlElement.parentElement); + else return undefined; + }; - if (!get(Container.focusedObject) && this.shouldFocusByDefault()) { - this.focus(); + if (!this.htmlElement) { + console.error('No html element found for', this); + return; + } else if (this.isInitialized) { + console.warn('Container already initialized', this); + } + + const parentContainer = this.htmlElement.parentElement + ? getParentContainer(this.htmlElement.parentElement) + : undefined; + if (parentContainer) { + parentContainer.addChild(this); + } else { + console.error('No parent container found for', this.htmlElement); + } + + if (!get(Container.focusedObject) && this.shouldFocusByDefault()) { + this.focus(); + } + } + + _unmountContainer() { + console.log('Unmounting container', this); + const isFocusedWithin = get(this.hasFocusWithin); + + if (this.htmlElement) { + Container.objects.delete(this.htmlElement); + } + + const parent = this.parent; + if (parent) { + parent.removeChild(this); + if (isFocusedWithin) { + parent.focus(); } + } + } + + private static createRegisterer( + _container?: Container, + flowDirection: FlowDirection = 'vertical' + ): Registerer { + const container = _container || new Container().setDirection(flowDirection); + + return (htmlElement: HTMLElement) => { + console.log('Registering', htmlElement, container); + container.setHtmlElement(htmlElement); return { destroy: () => { - this.removeHtmlElement(); + container.parent?.removeChild(container); + Container.objects.delete(htmlElement); } }; }; } - getHtmlElementRegisterer(): Registerer { - return (htmlElement: HTMLElement) => { - if (this.children.length > 0) { - console.warn('Registering an html element to a container that has children.'); - for (const child of this.children) { - this.removeChild(child); - } - } - this.addHtmlElement(htmlElement); - return { - destroy: () => { - this.removeHtmlElement(); - } - }; - }; + static getRegisterer(flowDirection: FlowDirection = 'vertical'): Registerer { + return (htmlElement: HTMLElement) => + this.createRegisterer(undefined, flowDirection)(htmlElement); + } + + getRegisterer(): Registerer { + return (htmlElement: HTMLElement) => Container.createRegisterer(this)(htmlElement); + } + + static getStores(element: HTMLElement) { + return Container.objects.get(element)?.getStores(); } getStores(): { container: Container; hasFocus: Readable; hasFocusWithin: Readable; + registerer: Registerer; } { return { container: this, hasFocus: this.hasFocus, - hasFocusWithin: this.hasFocusWithin + hasFocusWithin: this.hasFocusWithin, + registerer: this.getRegisterer() }; } private addChild(child: Container) { this.children.push(child); child.parent = this; - this.htmlElement = undefined; return this; } @@ -203,21 +288,16 @@ export class Container { return this; } - private addHtmlElement(htmlElement: HTMLElement) { - if (this.children.length > 0) { - console.warn('Adding an html element to a container that has children.'); - for (const child of this.children) { - this.removeChild(child); - } - } - this.htmlElement = htmlElement; - return this; - } - - private removeHtmlElement() { - this.htmlElement = undefined; - return this; - } + // private addHtmlElement(htmlElement: HTMLElement) { + // if (this.children.length > 0) { + // console.warn('Adding an html element to a container that has children.'); + // for (const child of this.children) { + // this.removeChild(child); + // } + // } + // this.htmlElement = htmlElement; + // return this; + // } private shouldFocusByDefault(): boolean { return this.focusByDefault || this.parent?.shouldFocusByDefault() || false; @@ -229,7 +309,12 @@ export function handleKeyboardNavigation(event: KeyboardEvent) { if (!currentlyFocusedObject) { console.error('No focused object!!!'); - mainContainer.focus(); + // Find object that can be focused + Container.objects.forEach((container) => { + if (container.isFocusable()) { + container.focus(); + } + }); return; } @@ -247,6 +332,8 @@ export function handleKeyboardNavigation(event: KeyboardEvent) { } export const focusedObject = Container.focusedObject; -export const mainContainer = new Container('main') - .setDirection('horizontal') - .setFocusByDefault(true); +// export const mainContainer = new Container('main') +// .setDirection('horizontal') +// .setFocusByDefault(true); + +export const registerer = Container.getRegisterer(); diff --git a/src/lib/components-new/NavbarItem.svelte b/src/lib/components-new/NavbarItem.svelte index 945f056..2451c80 100644 --- a/src/lib/components-new/NavbarItem.svelte +++ b/src/lib/components-new/NavbarItem.svelte @@ -1,31 +1,28 @@ - + +
+ + +
+
diff --git a/src/lib/components/Carousel/CarouselPlaceholderItems.svelte b/src/lib/components/Carousel/CarouselPlaceholderItems.svelte index 6cb4710..3797076 100644 --- a/src/lib/components/Carousel/CarouselPlaceholderItems.svelte +++ b/src/lib/components/Carousel/CarouselPlaceholderItems.svelte @@ -1,37 +1,31 @@

- Index: {$focusIndexStore} + Index: {$focusIndex}

{#each Array(10) as _, i (i)} -
-
+ {/each} diff --git a/src/lib/components/Selectable.svelte b/src/lib/components/Selectable.svelte index c42bd4d..fbaff60 100644 --- a/src/lib/components/Selectable.svelte +++ b/src/lib/components/Selectable.svelte @@ -2,13 +2,13 @@ import { Container } from '../actions/focusAction'; export let container: Container; - const registerer = container.getHtmlElementRegisterer(); + const registerer = container.getRegisterer(); export let handleClick = () => { container.focus(); }; - diff --git a/src/lib/pages/LibraryPage.svelte b/src/lib/pages/LibraryPage.svelte index 566a854..5767e9c 100644 --- a/src/lib/pages/LibraryPage.svelte +++ b/src/lib/pages/LibraryPage.svelte @@ -1,12 +1,9 @@ -
+
LibraryPage
- - - -
+ + + + + + diff --git a/src/lib/pages/ManagePage.svelte b/src/lib/pages/ManagePage.svelte index 586b290..40c7d39 100644 --- a/src/lib/pages/ManagePage.svelte +++ b/src/lib/pages/ManagePage.svelte @@ -1,8 +1,5 @@ -
ManagePage
+ManagePage diff --git a/src/lib/pages/MoviesPage.svelte b/src/lib/pages/MoviesPage.svelte index 4cfee65..080ce80 100644 --- a/src/lib/pages/MoviesPage.svelte +++ b/src/lib/pages/MoviesPage.svelte @@ -1,8 +1,5 @@ -
MoviesPage
+MoviesPage diff --git a/src/lib/pages/SearchPage.svelte b/src/lib/pages/SearchPage.svelte index bc177b0..30ff288 100644 --- a/src/lib/pages/SearchPage.svelte +++ b/src/lib/pages/SearchPage.svelte @@ -1,8 +1,5 @@ -
SearchPage
+SearchPage diff --git a/src/lib/pages/SeriesPage.svelte b/src/lib/pages/SeriesPage.svelte index 0040991..cbab00c 100644 --- a/src/lib/pages/SeriesPage.svelte +++ b/src/lib/pages/SeriesPage.svelte @@ -1,8 +1,5 @@ -
SeriesPage
+SeriesPage diff --git a/vite.config.ts b/vite.config.ts index a105265..1d6601e 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,7 +5,17 @@ import viteLegacyPlugin from '@vitejs/plugin-legacy'; // https://vitejs.dev/config/ export default defineConfig({ - plugins: [viteLegacyPlugin(), svelte(), viteSingleFile()], + plugins: [ + viteLegacyPlugin({ + // targets: ['chrome >= 64', 'edge >= 79', 'safari >= 11.1', 'firefox >= 67'], + // ignoreBrowserslistConfig: true, + renderLegacyChunks: true, + // modernPolyfills: ['es/global-this'] + modernPolyfills: true + }), + svelte(), + viteSingleFile() + ], optimizeDeps: { exclude: ['svelte-navigator'] } // base: '/dist',