diff --git a/src/kicanvas/elements/kicanvas-embed.ts b/src/kicanvas/elements/kicanvas-embed.ts
index f5f30549..1c63bdc2 100644
--- a/src/kicanvas/elements/kicanvas-embed.ts
+++ b/src/kicanvas/elements/kicanvas-embed.ts
@@ -14,6 +14,8 @@ import {
} from "../../base/web-components";
import { KCUIElement } from "../../kc-ui";
import kc_ui_styles from "../../kc-ui/kc-ui.css";
+import type { BoardViewer } from "../../viewers/board/viewer";
+import type { SchematicViewer } from "../../viewers/schematic/viewer";
import { Project } from "../project";
import { FetchFileSystem, VirtualFileSystem } from "../services/vfs";
import type { KCBoardAppElement } from "./kc-board/app";
@@ -95,7 +97,10 @@ class KiCanvasEmbedElement extends KCUIElement {
});
}
- async #setup_events() {}
+ async #setup_events() {
+ //Setup the deep link handler
+ window.addEventListener('hashchange', handleDeepLink);
+ }
async #load_src() {
const sources = [];
@@ -160,7 +165,7 @@ class KiCanvasEmbedElement extends KCUIElement {
const focus_overlay =
(this.controls ?? "none") == "none" ||
- this.controlslist?.includes("nooverlay")
+ this.controlslist?.includes("nooverlay")
? null
: html``;
@@ -168,6 +173,40 @@ class KiCanvasEmbedElement extends KCUIElement {
${this.#schematic_app} ${this.#board_app} ${focus_overlay}
`;
}
+
+
+ async deepLinkSelect(filename: string, reference: string) {
+ //We assure the filetype
+ console.log("Active Page:", this.#project.active_page);
+ let page = this.#project.page_by_name(filename);
+ switch (page?.type) {
+ case "pcb":
+ this.#project.set_active_page(page);
+ const boardView = this.#board_app.viewer as BoardViewer;
+ boardView.resolve_loaded(false); //This fixes the viewer reload bug where you cant select element if coming from the same viewer as the loaded Barrier isnt renewed
+ await boardView.loaded;
+ boardView.select(reference);
+ boardView.zoom_to_selection();
+ break;
+
+ case "schematic":
+ this.#project.set_active_page(page);
+ const schView = this.#schematic_app.viewer as SchematicViewer;
+ schView.resolve_loaded(false);//This fixes the viewer reload bug where you cant select element if coming from the same viewer as the loaded Barrier isnt renewed
+ await schView.loaded;
+ schView.select(reference);
+ schView.zoom_to_selection();
+ break;
+
+ default:
+ console.log("Unknown file type");
+ break;
+ }
+
+
+
+
+ }
}
window.customElements.define("kicanvas-embed", KiCanvasEmbedElement);
@@ -195,3 +234,27 @@ document.body.appendChild(
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,0,0&family=Nunito:wght@300;400;500;600;700&display=swap"
crossorigin="anonymous" />`,
);
+
+function handleDeepLink() {
+ const hash = window.location.hash.substring(1);
+ if (hash) {
+ const regex = /^(?[^:]+):(?[^:]+):(?[^:]+)$/;
+ const match = hash.match(regex);
+ if (match && match.groups) {
+ const { id, file, reference } = match.groups;
+ console.log("ID:", id, " File:", file, " Reference:", reference);
+ const element = document.getElementById(id as string) as KiCanvasEmbedElement; //this should get us the kicanvas element
+ if (element instanceof KiCanvasEmbedElement) { //If embed element exists trigger its select
+ console.log(element);
+ element.scrollIntoView({ behavior: 'smooth' });
+ element.deepLinkSelect(file as string, reference as string); //Sends
+ } else {
+ console.log("Element is not a kicanvasEmbedElement");
+ }
+ } else {
+ console.log("Invalid format");
+ }
+
+ }
+ return null;
+}
diff --git a/src/kicanvas/project.ts b/src/kicanvas/project.ts
index 32c78822..439bdb3f 100644
--- a/src/kicanvas/project.ts
+++ b/src/kicanvas/project.ts
@@ -301,6 +301,15 @@ export class Project extends EventTarget implements IDisposable {
return this.#pages_by_path.get(project_path);
}
+ public page_by_name(filename: string) {
+ for (const page of this.#pages_by_path.values()) {
+ if (page.filename === filename) {
+ return page;
+ }
+ }
+ return null;
+ }
+
public async download(name: string) {
if (this.#pages_by_path.has(name)) {
name = this.#pages_by_path.get(name)!.filename;
@@ -351,7 +360,7 @@ export class ProjectPage {
public sheet_path: string,
public name?: string,
public page?: string,
- ) {}
+ ) { }
/**
* A unique identifier for this page within the project,
diff --git a/src/viewers/base/document-viewer.ts b/src/viewers/base/document-viewer.ts
index d8b148f4..43d0b3ae 100644
--- a/src/viewers/base/document-viewer.ts
+++ b/src/viewers/base/document-viewer.ts
@@ -74,16 +74,14 @@ export abstract class DocumentViewer<
log.info("Positioning camera");
this.zoom_to_page();
- // Mark the viewer as loaded and notify event listeners
- this.resolve_loaded(true);
-
- // Deselect any selected items.
+ // Deselect any selected items before marking as loaded to not cause a bug when changing page and selecting item
if (this.selected) {
this.selected = null;
}
-
// Draw
this.draw();
+ // Mark the viewer as loaded and notify event listeners
+ this.resolve_loaded(true);
});
}
@@ -152,7 +150,7 @@ export abstract class DocumentViewer<
`Unable to select item ${item}, could not find an object that matched.`,
);
}
-
+ console.log("Reference found and loadded")
this.selected = item ?? null;
}
}
diff --git a/src/viewers/base/viewer.ts b/src/viewers/base/viewer.ts
index 3a497006..34add7c3 100644
--- a/src/viewers/base/viewer.ts
+++ b/src/viewers/base/viewer.ts
@@ -125,10 +125,12 @@ export abstract class Viewer extends EventTarget {
public abstract load(src: any): Promise;
- protected resolve_loaded(value: boolean) {
+ public resolve_loaded(value: boolean) {
if (value) {
this.loaded.open();
this.dispatchEvent(new KiCanvasLoadEvent());
+ } else { //To enable reload awaiting
+ this.loaded = new Barrier();
}
}