From 9c081f2eeaa9cf50dba1a6013db5764125e694a8 Mon Sep 17 00:00:00 2001 From: patnorris Date: Tue, 10 Oct 2023 19:42:42 +0100 Subject: [PATCH 01/18] Refactor Bebb related code --- src/PersonalWebSpace_backend/main.mo | 1 - .../components/ProtocolEntity.svelte | 4 +- .../components/SpaceNeighbors.svelte | 152 +++++----------- .../helpers/bebb_utils.ts | 163 ++++++++++++++++++ 4 files changed, 206 insertions(+), 114 deletions(-) create mode 100644 src/PersonalWebSpace_frontend/helpers/bebb_utils.ts diff --git a/src/PersonalWebSpace_backend/main.mo b/src/PersonalWebSpace_backend/main.mo index 4a46978..3a33b99 100644 --- a/src/PersonalWebSpace_backend/main.mo +++ b/src/PersonalWebSpace_backend/main.mo @@ -24,7 +24,6 @@ import HTTP "./Http"; import Stoic "./EXT/Stoic"; -import Protocol "./Protocol"; import Testable "mo:matchers/Testable"; import Blob "mo:base/Blob"; import Hash "mo:base/Hash"; diff --git a/src/PersonalWebSpace_frontend/components/ProtocolEntity.svelte b/src/PersonalWebSpace_frontend/components/ProtocolEntity.svelte index d170e97..d0bf31b 100644 --- a/src/PersonalWebSpace_frontend/components/ProtocolEntity.svelte +++ b/src/PersonalWebSpace_frontend/components/ProtocolEntity.svelte @@ -1,7 +1,7 @@ - + @@ -89,7 +89,7 @@ export const getStringForSpaceFromModel = (modelUrl) => { - + @@ -115,7 +115,7 @@ export const getStringForSpaceFromUserUploadedModel = () => { - + @@ -139,7 +139,7 @@ export const getStringForSpaceFromVideoFile = (videoUrl) => { - + @@ -166,7 +166,7 @@ export const getStringForSpaceFrom360VideoFile = (videoUrl) => { - + @@ -188,7 +188,7 @@ export const getStringForSpaceFromImageFile = (imageUrl) => { - + @@ -215,7 +215,7 @@ export const getStringForSpaceFrom360ImageFile = (imageUrl) => { - + diff --git a/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte b/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte index 6d98f28..e4a4e4a 100644 --- a/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte +++ b/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte @@ -13,9 +13,12 @@ import { canisterId as PersonalWebSpace_frontend_canister_id } from "canisters/PersonalWebSpace_frontend"; import type { BebbEntityInitiationObject, + BebbEntityPreview, } from "../helpers/bebb_utils"; import { createBebbEntity, + getBebbEntityUrlPreview, + getBebbEntityImagePreviewFromAframeHtml, } from "../helpers/bebb_utils"; let webHostedGlbModelUrl : string = ""; @@ -163,14 +166,33 @@ const spaceId = spaceResponse.Ok.id; setSpaceWasCreated(); // Protocol integration: create Space as Entity in Protocol - const externalId = `https://${PersonalWebSpace_frontend_canister_id}${appDomain}/#/space/${spaceId}`; + const spaceUrl = `https://${PersonalWebSpace_frontend_canister_id}${appDomain}/#/space/${spaceId}`; + const entitySpecificFields = { + externalId: spaceUrl, + }; + + const entityPreviews = []; + try { + const urlSpacePreview : BebbEntityPreview = await getBebbEntityUrlPreview(spaceUrl); + entityPreviews.push(urlSpacePreview); + } catch (error) { + console.error("Error creating url preview for space: ", error); + }; + try { + const imageSpacePreview : BebbEntityPreview = await getBebbEntityImagePreviewFromAframeHtml(spaceHtml); + entityPreviews.push(imageSpacePreview); + } catch (error) { + console.error("Error creating image preview for space: ", error); + }; + let entityInitiationObject : BebbEntityInitiationObject = { settings: [], entityType: { 'Resource' : { 'Web' : null } }, name: ["Personal Web Space"], description: ["Flaming Hot Personal Web Space"], keywords: [["NFT", "Space", "Open Internet Metaverse", "heeyah"]] as [Array], - entitySpecificFields: [externalId], + entitySpecificFields: [JSON.stringify(entitySpecificFields)], + previews: [entityPreviews], }; const spaceEntityIdResponse = await createBebbEntity(entityInitiationObject); // @ts-ignore diff --git a/src/PersonalWebSpace_frontend/pages/DownloadFileExample.svelte b/src/PersonalWebSpace_frontend/pages/DownloadFileExample.svelte index 4996555..d9b806e 100644 --- a/src/PersonalWebSpace_frontend/pages/DownloadFileExample.svelte +++ b/src/PersonalWebSpace_frontend/pages/DownloadFileExample.svelte @@ -43,7 +43,7 @@ onMount(addAFrameTestRoom); - + diff --git a/src/PersonalWebSpace_frontend/pages/Space.svelte b/src/PersonalWebSpace_frontend/pages/Space.svelte index 83d93de..c689c15 100644 --- a/src/PersonalWebSpace_frontend/pages/Space.svelte +++ b/src/PersonalWebSpace_frontend/pages/Space.svelte @@ -27,9 +27,10 @@ import { canisterId as backendCanisterId } from "canisters/PersonalWebSpace_backend"; import type { BebbEntity, + BebbEntityAndBridge, } from "../helpers/bebb_utils"; import { - getConnectedEntitiesInBebb, + getConnectedEntitiesAndBridgesInBebb, } from "../helpers/bebb_utils"; @@ -1300,7 +1301,7 @@ }; }; - const entityHasValidUrl = (entity: Entity) => { + const entityHasValidUrl = (entity: BebbEntity) => { return isValidUrl(entity.entitySpecificFields); }; @@ -1334,22 +1335,84 @@ }; }; - function loadNeighborsIn3D(spaceNeighbors: Entity[]) { + function loadNeighborsIn3D(spaceNeighbors: BebbEntityAndBridge[]) { // Create a new entity for each neighbor let neighborIndex = 0; for (const neighbor of spaceNeighbors) { - // Only display neighbors that have a valid URL - if (entityHasValidUrl(neighbor)) { - // Create a new entity for the neighbor - let neighborEntity = document.createElement('a-entity'); - // Set properties on the new neighbor entity - neighborEntity.setAttribute('id', `OIM-VR-neighbor-${neighbor.id}`); - neighborEntity.setAttribute('web-portal', `url:${neighbor.entitySpecificFields}; text:${neighbor.name[0] || "Neighbor " + neighborIndex};`); - neighborEntity.setAttribute('position', `${-5 - neighborIndex*3} 1.25 -10`); // Position all Neighbors along one line - // Add the neighbor entity to the scene - let scene = document.querySelector('a-scene'); - scene.appendChild(neighborEntity); - neighborIndex++; + var hasAdditionalPresentationMetadata = false; + var additionalPresentationMetadata; + if (neighbor.bridge.entitySpecificFields) { + try { + const entitySpecificFields = JSON.parse(neighbor.bridge.entitySpecificFields); + if (entitySpecificFields.presentationMetadata) { + additionalPresentationMetadata = entitySpecificFields.presentationMetadata; + hasAdditionalPresentationMetadata = true; + }; + } catch(error) { + hasAdditionalPresentationMetadata = false; + }; + }; + if (hasAdditionalPresentationMetadata) { + var neighborUrl; + try { + if (neighbor.entity.previews && neighbor.entity.previews[0]) { + var urlPreview; + for (const preview of neighbor.entity.previews) { + // @ts-ignore + if (preview.previewType.hasOwnProperty('Other') && preview.previewType.Other === "URL") { + var enc = new TextDecoder("utf-8"); + const url = enc.decode(preview.previewData); + if (isValidUrl(url)) { + neighborUrl = url; + urlPreview = preview; + }; + }; + }; + } else { + if (neighbor.entity.entitySpecificFields) { + const entitySpecificFields = JSON.parse(neighbor.entity.entitySpecificFields); + if (entitySpecificFields.externalId && isValidUrl(entitySpecificFields.externalId)) { + neighborUrl = entitySpecificFields.externalId; + }; + }; + }; + } catch(error) { + console.error("Neighbor doesn't have a valid url ", error); + }; + if (neighborUrl) { + // Create a new entity for the neighbor + let neighborEntity = document.createElement('a-entity'); + // Set properties on the new neighbor entity + neighborEntity.setAttribute('id', `OIM-VR-neighbor-${neighbor.entity.id}`); + if (additionalPresentationMetadata && additionalPresentationMetadata.data && additionalPresentationMetadata.data.width && additionalPresentationMetadata.data.height) { + neighborEntity.setAttribute('web-portal', `url:${neighborUrl}; text:${neighbor.entity.name[0] || "Neighbor " + neighborIndex}; width:${additionalPresentationMetadata.data.width}; height:${additionalPresentationMetadata.data.height}`); + } else { + neighborEntity.setAttribute('web-portal', `url:${neighborUrl}; text:${neighbor.entity.name[0] || "Neighbor " + neighborIndex};`); + }; + if (additionalPresentationMetadata && additionalPresentationMetadata.data && additionalPresentationMetadata.data.position) { + neighborEntity.setAttribute('position', additionalPresentationMetadata.data.position); + } else { + neighborEntity.setAttribute('position', `${-5 - neighborIndex*3} 1.25 -10`); // Position all Neighbors along one line + }; + // Add the neighbor entity to the scene + let scene = document.querySelector('a-scene'); + scene.appendChild(neighborEntity); + neighborIndex++; + }; + } else { // no additional presentation metadata + // Only display neighbors that have a valid URL + if (entityHasValidUrl(neighbor.entity)) { + // Create a new entity for the neighbor + let neighborEntity = document.createElement('a-entity'); + // Set properties on the new neighbor entity + neighborEntity.setAttribute('id', `OIM-VR-neighbor-${neighbor.entity.id}`); + neighborEntity.setAttribute('web-portal', `url:${neighbor.entity.entitySpecificFields}; text:${neighbor.entity.name[0] || "Neighbor " + neighborIndex};`); + neighborEntity.setAttribute('position', `${-5 - neighborIndex*3} 1.25 -10`); // Position all Neighbors along one line + // Add the neighbor entity to the scene + let scene = document.querySelector('a-scene'); + scene.appendChild(neighborEntity); + neighborIndex++; + }; }; }; }; @@ -1357,11 +1420,11 @@ const loadSpaceNeighborsIn3D = async () => { // Load the Space's Neighbors from Bebb Protocol and display them in 3D in the scene const spaceEntityId = extractSpaceEntityId(); - let retrievedNeighborEntities : BebbEntity[] = []; + let retrievedNeighborEntities : BebbEntityAndBridge[] = []; try { - const getConnectedEntitiesResponse = await getConnectedEntitiesInBebb(spaceEntityId); + const getConnectedEntitiesResponse = await getConnectedEntitiesAndBridgesInBebb(spaceEntityId, "from", {OwnerCreated: true}); for (var j = 0; j < getConnectedEntitiesResponse.length; j++) { - const connectedEntity : BebbEntity = getConnectedEntitiesResponse[j]; + const connectedEntity : BebbEntityAndBridge = getConnectedEntitiesResponse[j]; retrievedNeighborEntities.push(connectedEntity); }; } catch(err) { diff --git a/src/integrations/BebbProtocol/bebb.did b/src/integrations/BebbProtocol/bebb.did index 9f32987..bff4fb8 100644 --- a/src/integrations/BebbProtocol/bebb.did +++ b/src/integrations/BebbProtocol/bebb.did @@ -1,186 +1,198 @@ -type Time = int; -type EntityUpdateObject = - record { - description: opt text; - id: text; - keywords: opt vec text; - name: opt text; - previews: opt vec EntityPreview; - settings: opt EntitySettings; - }; -type EntityTypeResourceTypes = - variant { - Content; - DigitalAsset; - Web; - }; -type EntityType = - variant { - Other: text; - Resource: EntityTypeResourceTypes; - }; -type EntitySettings = record {}; -type EntityResult = - variant { - Err: EntityErrors; - Ok: Entity; - }; -type EntityPreviewSupportedTypes = - variant { - Glb; - Gltf; - Jpg; - Other: text; - Png; - }; -type EntityPreview = - record { - previewData: blob; - previewType: EntityPreviewSupportedTypes; - }; -type EntityInitiationObject = - record { - description: opt text; - entitySpecificFields: opt text; - entityType: EntityType; - keywords: opt vec text; - name: opt text; - settings: opt EntitySettings; - }; -type EntityIdResult = - variant { - Err: EntityIdErrors; - Ok: text; - }; -type EntityIdErrors = - variant { - EntityNotFound; - Error; - PreviewTooLarge: int; - TooManyPreviews; - Unauthorized; - }; -type EntityErrors = - variant { - EntityNotFound; - Error; - Unauthorized: text; - }; -type EntityAttachedBridgesResult = - variant { - Err: EntityAttachedBridgesErrors; - Ok: EntityAttachedBridges; - }; -type EntityAttachedBridgesErrors = - variant { - EntityNotFound; - Error; - }; -type EntityAttachedBridges = vec EntityAttachedBridge; -type EntityAttachedBridge = - record { - bridgeType: BridgeType; - creationTime: Time; - id: text; - linkStatus: BridgeLinkStatus; - }; -type Entity = - record { - creationTimestamp: nat64; - creator: principal; - description: text; - entitySpecificFields: text; - entityType: EntityType; - fromIds: EntityAttachedBridges; - id: text; - keywords: vec text; - listOfEntitySpecificFieldKeys: vec text; - name: text; - owner: principal; - previews: vec EntityPreview; - settings: EntitySettings; - toIds: EntityAttachedBridges; - }; -type BridgeUpdateObject = - record { - description: opt text; - id: text; - keywords: opt vec text; - name: opt text; - settings: opt BridgeSettings; - }; -type BridgeType = - variant { - IsAttachedto; - IsPartOf; - IsRelatedto; - }; -type BridgeSettings = record {}; -type BridgeResult = - variant { - Err: BridgeErrors; - Ok: Bridge; - }; -type BridgeLinkStatus = - variant { - CreatedOther; - CreatedOwner; - }; -type BridgeInitiationObject = - record { - bridgeType: BridgeType; - description: opt text; - entitySpecificFields: opt text; - fromEntityId: text; - keywords: opt vec text; - name: opt text; - settings: opt BridgeSettings; - toEntityId: text; - }; -type BridgeIdResult = - variant { - Err: BridgeIdErrors; - Ok: text; - }; -type BridgeIdErrors = - variant { - BridgeNotFound; - Error; - Unauthorized; - }; -type BridgeErrors = - variant { - BridgeNotFound; - Error; - Unauthorized: text; - }; -type Bridge = - record { - bridgeType: BridgeType; - creationTimestamp: nat64; - creator: principal; - description: text; - entitySpecificFields: text; - fromEntityId: text; - id: text; - keywords: vec text; - listOfEntitySpecificFieldKeys: vec text; - name: text; - owner: principal; - settings: BridgeSettings; - toEntityId: text; - }; -service : { - create_bridge: (BridgeInitiationObject) -> (BridgeIdResult); - create_entity: (EntityInitiationObject) -> (EntityIdResult); - delete_bridge: (text) -> (BridgeIdResult); - delete_entity: (text) -> (EntityIdResult); - get_bridge: (text) -> (BridgeResult) query; - get_entity: (text) -> (EntityResult) query; - get_from_bridge_ids_by_entity_id: (text) -> - (EntityAttachedBridgesResult) query; - get_to_bridge_ids_by_entity_id: (text) -> - (EntityAttachedBridgesResult) query; - update_bridge: (BridgeUpdateObject) -> (BridgeIdResult); - update_entity: (EntityUpdateObject) -> (EntityIdResult); -} +type Time = int; +type EntityUpdateObject = + record { + description: opt text; + id: text; + keywords: opt vec text; + name: opt text; + previews: opt vec EntityPreview; + settings: opt EntitySettings; + }; +type EntityTypeResourceTypes = + variant { + Content; + DigitalAsset; + Web; + }; +type EntityType = + variant { + Other: text; + Resource: EntityTypeResourceTypes; + }; +type EntitySettings = record {}; +type EntityResult = + variant { + Err: EntityErrors; + Ok: Entity; + }; +type EntityPreviewSupportedTypes = + variant { + Glb; + Gltf; + Jpg; + Other: text; + Png; + }; +type EntityPreview = + record { + previewData: blob; + previewType: EntityPreviewSupportedTypes; + }; +type EntityInitiationObject = + record { + description: opt text; + entitySpecificFields: opt text; + entityType: EntityType; + keywords: opt vec text; + name: opt text; + previews: opt vec EntityPreview; + settings: opt EntitySettings; + }; +type EntityIdResult = + variant { + Err: EntityIdErrors; + Ok: text; + }; +type EntityIdErrors = + variant { + EntityNotFound; + Error; + PreviewTooLarge: int; + TooManyPreviews; + Unauthorized; + }; +type EntityFilterCriterion = + record { + criterionKey: text; + criterionValue: text; + }; +type EntityErrors = + variant { + EntityNotFound; + Error; + Unauthorized: text; + }; +type EntityAttachedBridgesResult = + variant { + Err: EntityAttachedBridgesErrors; + Ok: EntityAttachedBridges; + }; +type EntityAttachedBridgesErrors = + variant { + EntityNotFound; + Error; + }; +type EntityAttachedBridges = vec EntityAttachedBridge; +type EntityAttachedBridge = + record { + bridgeType: BridgeType; + creationTime: Time; + id: text; + linkStatus: BridgeLinkStatus; + }; +type Entity = + record { + creationTimestamp: nat64; + creator: principal; + description: text; + entitySpecificFields: text; + entityType: EntityType; + fromIds: EntityAttachedBridges; + id: text; + keywords: vec text; + listOfEntitySpecificFieldKeys: vec text; + name: text; + owner: principal; + previews: vec EntityPreview; + settings: EntitySettings; + toIds: EntityAttachedBridges; + }; +type EntitiesResult = + variant { + Err: EntityErrors; + Ok: vec Entity; + }; +type BridgeUpdateObject = + record { + description: opt text; + id: text; + keywords: opt vec text; + name: opt text; + settings: opt BridgeSettings; + }; +type BridgeType = + variant { + IsAttachedto; + IsPartOf; + IsRelatedto; + }; +type BridgeSettings = record {}; +type BridgeResult = + variant { + Err: BridgeErrors; + Ok: Bridge; + }; +type BridgeLinkStatus = + variant { + CreatedOther; + CreatedOwner; + }; +type BridgeInitiationObject = + record { + bridgeType: BridgeType; + description: opt text; + entitySpecificFields: opt text; + fromEntityId: text; + keywords: opt vec text; + name: opt text; + settings: opt BridgeSettings; + toEntityId: text; + }; +type BridgeIdResult = + variant { + Err: BridgeIdErrors; + Ok: text; + }; +type BridgeIdErrors = + variant { + BridgeNotFound; + Error; + Unauthorized; + }; +type BridgeErrors = + variant { + BridgeNotFound; + Error; + Unauthorized: text; + }; +type Bridge = + record { + bridgeType: BridgeType; + creationTimestamp: nat64; + creator: principal; + description: text; + entitySpecificFields: text; + fromEntityId: text; + id: text; + keywords: vec text; + listOfEntitySpecificFieldKeys: vec text; + name: text; + owner: principal; + settings: BridgeSettings; + toEntityId: text; + }; +service : { + create_bridge: (BridgeInitiationObject) -> (BridgeIdResult); + create_entity: (EntityInitiationObject) -> (EntityIdResult); + delete_bridge: (text) -> (BridgeIdResult); + delete_entity: (text) -> (EntityIdResult); + get_bridge: (text) -> (BridgeResult) query; + get_entity: (text) -> (EntityResult) query; + get_from_bridge_ids_by_entity_id: (text) -> + (EntityAttachedBridgesResult) query; + get_to_bridge_ids_by_entity_id: (text) -> + (EntityAttachedBridgesResult) query; + match_entities: (vec EntityFilterCriterion) -> (EntitiesResult) query; + update_bridge: (BridgeUpdateObject) -> (BridgeIdResult); + update_entity: (EntityUpdateObject) -> (EntityIdResult); +} diff --git a/src/integrations/BebbProtocol/bebb.did.d.ts b/src/integrations/BebbProtocol/bebb.did.d.ts index 8e4f1cb..2a09fb0 100644 --- a/src/integrations/BebbProtocol/bebb.did.d.ts +++ b/src/integrations/BebbProtocol/bebb.did.d.ts @@ -1,140 +1,151 @@ -import type { Principal } from '@dfinity/principal'; -import type { ActorMethod } from '@dfinity/agent'; - -export interface Bridge { - 'id' : string, - 'toEntityId' : string, - 'creator' : Principal, - 'fromEntityId' : string, - 'owner' : Principal, - 'creationTimestamp' : bigint, - 'name' : string, - 'description' : string, - 'keywords' : Array, - 'settings' : BridgeSettings, - 'listOfEntitySpecificFieldKeys' : Array, - 'bridgeType' : BridgeType, - 'entitySpecificFields' : string, -} -export type BridgeErrors = { 'Error' : null } | - { 'Unauthorized' : string } | - { 'BridgeNotFound' : null }; -export type BridgeIdErrors = { 'Error' : null } | - { 'Unauthorized' : null } | - { 'BridgeNotFound' : null }; -export type BridgeIdResult = { 'Ok' : string } | - { 'Err' : BridgeIdErrors }; -export interface BridgeInitiationObject { - 'toEntityId' : string, - 'fromEntityId' : string, - 'name' : [] | [string], - 'description' : [] | [string], - 'keywords' : [] | [Array], - 'settings' : [] | [BridgeSettings], - 'bridgeType' : BridgeType, - 'entitySpecificFields' : [] | [string], -} -export type BridgeLinkStatus = { 'CreatedOther' : null } | - { 'CreatedOwner' : null }; -export type BridgeResult = { 'Ok' : Bridge } | - { 'Err' : BridgeErrors }; -export type BridgeSettings = {}; -export type BridgeType = { 'IsPartOf' : null } | - { 'IsAttachedto' : null } | - { 'IsRelatedto' : null }; -export interface BridgeUpdateObject { - 'id' : string, - 'name' : [] | [string], - 'description' : [] | [string], - 'keywords' : [] | [Array], - 'settings' : [] | [BridgeSettings], -} -export interface Entity { - 'id' : string, - 'creator' : Principal, - 'toIds' : EntityAttachedBridges, - 'previews' : Array, - 'owner' : Principal, - 'creationTimestamp' : bigint, - 'name' : string, - 'fromIds' : EntityAttachedBridges, - 'description' : string, - 'keywords' : Array, - 'settings' : EntitySettings, - 'listOfEntitySpecificFieldKeys' : Array, - 'entityType' : EntityType, - 'entitySpecificFields' : string, -} -export interface EntityAttachedBridge { - 'id' : string, - 'creationTime' : Time, - 'bridgeType' : BridgeType, - 'linkStatus' : BridgeLinkStatus, -} -export type EntityAttachedBridges = Array; -export type EntityAttachedBridgesErrors = { 'Error' : null } | - { 'EntityNotFound' : null }; -export type EntityAttachedBridgesResult = { 'Ok' : EntityAttachedBridges } | - { 'Err' : EntityAttachedBridgesErrors }; -export type EntityErrors = { 'Error' : null } | - { 'EntityNotFound' : null } | - { 'Unauthorized' : string }; -export type EntityIdErrors = { 'Error' : null } | - { 'PreviewTooLarge' : bigint } | - { 'EntityNotFound' : null } | - { 'TooManyPreviews' : null } | - { 'Unauthorized' : null }; -export type EntityIdResult = { 'Ok' : string } | - { 'Err' : EntityIdErrors }; -export interface EntityInitiationObject { - 'name' : [] | [string], - 'description' : [] | [string], - 'keywords' : [] | [Array], - 'settings' : [] | [EntitySettings], - 'entityType' : EntityType, - 'entitySpecificFields' : [] | [string], -} -export interface EntityPreview { - 'previewData' : Uint8Array | number[], - 'previewType' : EntityPreviewSupportedTypes, -} -export type EntityPreviewSupportedTypes = { 'Glb' : null } | - { 'Jpg' : null } | - { 'Png' : null } | - { 'Gltf' : null } | - { 'Other' : string }; -export type EntityResult = { 'Ok' : Entity } | - { 'Err' : EntityErrors }; -export type EntitySettings = {}; -export type EntityType = { 'Other' : string } | - { 'Resource' : EntityTypeResourceTypes }; -export type EntityTypeResourceTypes = { 'Web' : null } | - { 'DigitalAsset' : null } | - { 'Content' : null }; -export interface EntityUpdateObject { - 'id' : string, - 'previews' : [] | [Array], - 'name' : [] | [string], - 'description' : [] | [string], - 'keywords' : [] | [Array], - 'settings' : [] | [EntitySettings], -} -export type Time = bigint; -export interface _SERVICE { - 'create_bridge' : ActorMethod<[BridgeInitiationObject], BridgeIdResult>, - 'create_entity' : ActorMethod<[EntityInitiationObject], EntityIdResult>, - 'delete_bridge' : ActorMethod<[string], BridgeIdResult>, - 'delete_entity' : ActorMethod<[string], EntityIdResult>, - 'get_bridge' : ActorMethod<[string], BridgeResult>, - 'get_entity' : ActorMethod<[string], EntityResult>, - 'get_from_bridge_ids_by_entity_id' : ActorMethod< - [string], - EntityAttachedBridgesResult - >, - 'get_to_bridge_ids_by_entity_id' : ActorMethod< - [string], - EntityAttachedBridgesResult - >, - 'update_bridge' : ActorMethod<[BridgeUpdateObject], BridgeIdResult>, - 'update_entity' : ActorMethod<[EntityUpdateObject], EntityIdResult>, -} +import type { Principal } from '@dfinity/principal'; +import type { ActorMethod } from '@dfinity/agent'; + +export interface Bridge { + 'id' : string, + 'toEntityId' : string, + 'creator' : Principal, + 'fromEntityId' : string, + 'owner' : Principal, + 'creationTimestamp' : bigint, + 'name' : string, + 'description' : string, + 'keywords' : Array, + 'settings' : BridgeSettings, + 'listOfEntitySpecificFieldKeys' : Array, + 'bridgeType' : BridgeType, + 'entitySpecificFields' : string, +} +export type BridgeErrors = { 'Error' : null } | + { 'Unauthorized' : string } | + { 'BridgeNotFound' : null }; +export type BridgeIdErrors = { 'Error' : null } | + { 'Unauthorized' : null } | + { 'BridgeNotFound' : null }; +export type BridgeIdResult = { 'Ok' : string } | + { 'Err' : BridgeIdErrors }; +export interface BridgeInitiationObject { + 'toEntityId' : string, + 'fromEntityId' : string, + 'name' : [] | [string], + 'description' : [] | [string], + 'keywords' : [] | [Array], + 'settings' : [] | [BridgeSettings], + 'bridgeType' : BridgeType, + 'entitySpecificFields' : [] | [string], +} +export type BridgeLinkStatus = { 'CreatedOther' : null } | + { 'CreatedOwner' : null }; +export type BridgeResult = { 'Ok' : Bridge } | + { 'Err' : BridgeErrors }; +export type BridgeSettings = {}; +export type BridgeType = { 'IsPartOf' : null } | + { 'IsAttachedto' : null } | + { 'IsRelatedto' : null }; +export interface BridgeUpdateObject { + 'id' : string, + 'name' : [] | [string], + 'description' : [] | [string], + 'keywords' : [] | [Array], + 'settings' : [] | [BridgeSettings], +} +export type EntitiesResult = { 'Ok' : Array } | + { 'Err' : EntityErrors }; +export interface Entity { + 'id' : string, + 'creator' : Principal, + 'toIds' : EntityAttachedBridges, + 'previews' : Array, + 'owner' : Principal, + 'creationTimestamp' : bigint, + 'name' : string, + 'fromIds' : EntityAttachedBridges, + 'description' : string, + 'keywords' : Array, + 'settings' : EntitySettings, + 'listOfEntitySpecificFieldKeys' : Array, + 'entityType' : EntityType, + 'entitySpecificFields' : string, +} +export interface EntityAttachedBridge { + 'id' : string, + 'creationTime' : Time, + 'bridgeType' : BridgeType, + 'linkStatus' : BridgeLinkStatus, +} +export type EntityAttachedBridges = Array; +export type EntityAttachedBridgesErrors = { 'Error' : null } | + { 'EntityNotFound' : null }; +export type EntityAttachedBridgesResult = { 'Ok' : EntityAttachedBridges } | + { 'Err' : EntityAttachedBridgesErrors }; +export type EntityErrors = { 'Error' : null } | + { 'EntityNotFound' : null } | + { 'Unauthorized' : string }; +export interface EntityFilterCriterion { + 'criterionKey' : string, + 'criterionValue' : string, +} +export type EntityIdErrors = { 'Error' : null } | + { 'PreviewTooLarge' : bigint } | + { 'EntityNotFound' : null } | + { 'TooManyPreviews' : null } | + { 'Unauthorized' : null }; +export type EntityIdResult = { 'Ok' : string } | + { 'Err' : EntityIdErrors }; +export interface EntityInitiationObject { + 'previews' : [] | [Array], + 'name' : [] | [string], + 'description' : [] | [string], + 'keywords' : [] | [Array], + 'settings' : [] | [EntitySettings], + 'entityType' : EntityType, + 'entitySpecificFields' : [] | [string], +} +export interface EntityPreview { + 'previewData' : Uint8Array | number[], + 'previewType' : EntityPreviewSupportedTypes, +} +export type EntityPreviewSupportedTypes = { 'Glb' : null } | + { 'Jpg' : null } | + { 'Png' : null } | + { 'Gltf' : null } | + { 'Other' : string }; +export type EntityResult = { 'Ok' : Entity } | + { 'Err' : EntityErrors }; +export type EntitySettings = {}; +export type EntityType = { 'Other' : string } | + { 'Resource' : EntityTypeResourceTypes }; +export type EntityTypeResourceTypes = { 'Web' : null } | + { 'DigitalAsset' : null } | + { 'Content' : null }; +export interface EntityUpdateObject { + 'id' : string, + 'previews' : [] | [Array], + 'name' : [] | [string], + 'description' : [] | [string], + 'keywords' : [] | [Array], + 'settings' : [] | [EntitySettings], +} +export type Time = bigint; +export interface _SERVICE { + 'create_bridge' : ActorMethod<[BridgeInitiationObject], BridgeIdResult>, + 'create_entity' : ActorMethod<[EntityInitiationObject], EntityIdResult>, + 'delete_bridge' : ActorMethod<[string], BridgeIdResult>, + 'delete_entity' : ActorMethod<[string], EntityIdResult>, + 'get_bridge' : ActorMethod<[string], BridgeResult>, + 'get_entity' : ActorMethod<[string], EntityResult>, + 'get_from_bridge_ids_by_entity_id' : ActorMethod< + [string], + EntityAttachedBridgesResult + >, + 'get_to_bridge_ids_by_entity_id' : ActorMethod< + [string], + EntityAttachedBridgesResult + >, + 'match_entities' : ActorMethod< + [Array], + EntitiesResult + >, + 'update_bridge' : ActorMethod<[BridgeUpdateObject], BridgeIdResult>, + 'update_entity' : ActorMethod<[EntityUpdateObject], EntityIdResult>, +} diff --git a/src/integrations/BebbProtocol/bebb.did.js b/src/integrations/BebbProtocol/bebb.did.js index 356f3f0..ebfcff7 100644 --- a/src/integrations/BebbProtocol/bebb.did.js +++ b/src/integrations/BebbProtocol/bebb.did.js @@ -1,166 +1,180 @@ -export const idlFactory = ({ IDL }) => { - const BridgeSettings = IDL.Record({}); - const BridgeType = IDL.Variant({ - 'IsPartOf' : IDL.Null, - 'IsAttachedto' : IDL.Null, - 'IsRelatedto' : IDL.Null, - }); - const BridgeInitiationObject = IDL.Record({ - 'toEntityId' : IDL.Text, - 'fromEntityId' : IDL.Text, - 'name' : IDL.Opt(IDL.Text), - 'description' : IDL.Opt(IDL.Text), - 'keywords' : IDL.Opt(IDL.Vec(IDL.Text)), - 'settings' : IDL.Opt(BridgeSettings), - 'bridgeType' : BridgeType, - 'entitySpecificFields' : IDL.Opt(IDL.Text), - }); - const BridgeIdErrors = IDL.Variant({ - 'Error' : IDL.Null, - 'Unauthorized' : IDL.Null, - 'BridgeNotFound' : IDL.Null, - }); - const BridgeIdResult = IDL.Variant({ - 'Ok' : IDL.Text, - 'Err' : BridgeIdErrors, - }); - const EntitySettings = IDL.Record({}); - const EntityTypeResourceTypes = IDL.Variant({ - 'Web' : IDL.Null, - 'DigitalAsset' : IDL.Null, - 'Content' : IDL.Null, - }); - const EntityType = IDL.Variant({ - 'Other' : IDL.Text, - 'Resource' : EntityTypeResourceTypes, - }); - const EntityInitiationObject = IDL.Record({ - 'name' : IDL.Opt(IDL.Text), - 'description' : IDL.Opt(IDL.Text), - 'keywords' : IDL.Opt(IDL.Vec(IDL.Text)), - 'settings' : IDL.Opt(EntitySettings), - 'entityType' : EntityType, - 'entitySpecificFields' : IDL.Opt(IDL.Text), - }); - const EntityIdErrors = IDL.Variant({ - 'Error' : IDL.Null, - 'PreviewTooLarge' : IDL.Int, - 'EntityNotFound' : IDL.Null, - 'TooManyPreviews' : IDL.Null, - 'Unauthorized' : IDL.Null, - }); - const EntityIdResult = IDL.Variant({ - 'Ok' : IDL.Text, - 'Err' : EntityIdErrors, - }); - const Bridge = IDL.Record({ - 'id' : IDL.Text, - 'toEntityId' : IDL.Text, - 'creator' : IDL.Principal, - 'fromEntityId' : IDL.Text, - 'owner' : IDL.Principal, - 'creationTimestamp' : IDL.Nat64, - 'name' : IDL.Text, - 'description' : IDL.Text, - 'keywords' : IDL.Vec(IDL.Text), - 'settings' : BridgeSettings, - 'listOfEntitySpecificFieldKeys' : IDL.Vec(IDL.Text), - 'bridgeType' : BridgeType, - 'entitySpecificFields' : IDL.Text, - }); - const BridgeErrors = IDL.Variant({ - 'Error' : IDL.Null, - 'Unauthorized' : IDL.Text, - 'BridgeNotFound' : IDL.Null, - }); - const BridgeResult = IDL.Variant({ 'Ok' : Bridge, 'Err' : BridgeErrors }); - const Time = IDL.Int; - const BridgeLinkStatus = IDL.Variant({ - 'CreatedOther' : IDL.Null, - 'CreatedOwner' : IDL.Null, - }); - const EntityAttachedBridge = IDL.Record({ - 'id' : IDL.Text, - 'creationTime' : Time, - 'bridgeType' : BridgeType, - 'linkStatus' : BridgeLinkStatus, - }); - const EntityAttachedBridges = IDL.Vec(EntityAttachedBridge); - const EntityPreviewSupportedTypes = IDL.Variant({ - 'Glb' : IDL.Null, - 'Jpg' : IDL.Null, - 'Png' : IDL.Null, - 'Gltf' : IDL.Null, - 'Other' : IDL.Text, - }); - const EntityPreview = IDL.Record({ - 'previewData' : IDL.Vec(IDL.Nat8), - 'previewType' : EntityPreviewSupportedTypes, - }); - const Entity = IDL.Record({ - 'id' : IDL.Text, - 'creator' : IDL.Principal, - 'toIds' : EntityAttachedBridges, - 'previews' : IDL.Vec(EntityPreview), - 'owner' : IDL.Principal, - 'creationTimestamp' : IDL.Nat64, - 'name' : IDL.Text, - 'fromIds' : EntityAttachedBridges, - 'description' : IDL.Text, - 'keywords' : IDL.Vec(IDL.Text), - 'settings' : EntitySettings, - 'listOfEntitySpecificFieldKeys' : IDL.Vec(IDL.Text), - 'entityType' : EntityType, - 'entitySpecificFields' : IDL.Text, - }); - const EntityErrors = IDL.Variant({ - 'Error' : IDL.Null, - 'EntityNotFound' : IDL.Null, - 'Unauthorized' : IDL.Text, - }); - const EntityResult = IDL.Variant({ 'Ok' : Entity, 'Err' : EntityErrors }); - const EntityAttachedBridgesErrors = IDL.Variant({ - 'Error' : IDL.Null, - 'EntityNotFound' : IDL.Null, - }); - const EntityAttachedBridgesResult = IDL.Variant({ - 'Ok' : EntityAttachedBridges, - 'Err' : EntityAttachedBridgesErrors, - }); - const BridgeUpdateObject = IDL.Record({ - 'id' : IDL.Text, - 'name' : IDL.Opt(IDL.Text), - 'description' : IDL.Opt(IDL.Text), - 'keywords' : IDL.Opt(IDL.Vec(IDL.Text)), - 'settings' : IDL.Opt(BridgeSettings), - }); - const EntityUpdateObject = IDL.Record({ - 'id' : IDL.Text, - 'previews' : IDL.Opt(IDL.Vec(EntityPreview)), - 'name' : IDL.Opt(IDL.Text), - 'description' : IDL.Opt(IDL.Text), - 'keywords' : IDL.Opt(IDL.Vec(IDL.Text)), - 'settings' : IDL.Opt(EntitySettings), - }); - return IDL.Service({ - 'create_bridge' : IDL.Func([BridgeInitiationObject], [BridgeIdResult], []), - 'create_entity' : IDL.Func([EntityInitiationObject], [EntityIdResult], []), - 'delete_bridge' : IDL.Func([IDL.Text], [BridgeIdResult], []), - 'delete_entity' : IDL.Func([IDL.Text], [EntityIdResult], []), - 'get_bridge' : IDL.Func([IDL.Text], [BridgeResult], ['query']), - 'get_entity' : IDL.Func([IDL.Text], [EntityResult], ['query']), - 'get_from_bridge_ids_by_entity_id' : IDL.Func( - [IDL.Text], - [EntityAttachedBridgesResult], - ['query'], - ), - 'get_to_bridge_ids_by_entity_id' : IDL.Func( - [IDL.Text], - [EntityAttachedBridgesResult], - ['query'], - ), - 'update_bridge' : IDL.Func([BridgeUpdateObject], [BridgeIdResult], []), - 'update_entity' : IDL.Func([EntityUpdateObject], [EntityIdResult], []), - }); -}; -export const init = ({ IDL }) => { return []; }; +export const idlFactory = ({ IDL }) => { + const BridgeSettings = IDL.Record({}); + const BridgeType = IDL.Variant({ + 'IsPartOf' : IDL.Null, + 'IsAttachedto' : IDL.Null, + 'IsRelatedto' : IDL.Null, + }); + const BridgeInitiationObject = IDL.Record({ + 'toEntityId' : IDL.Text, + 'fromEntityId' : IDL.Text, + 'name' : IDL.Opt(IDL.Text), + 'description' : IDL.Opt(IDL.Text), + 'keywords' : IDL.Opt(IDL.Vec(IDL.Text)), + 'settings' : IDL.Opt(BridgeSettings), + 'bridgeType' : BridgeType, + 'entitySpecificFields' : IDL.Opt(IDL.Text), + }); + const BridgeIdErrors = IDL.Variant({ + 'Error' : IDL.Null, + 'Unauthorized' : IDL.Null, + 'BridgeNotFound' : IDL.Null, + }); + const BridgeIdResult = IDL.Variant({ + 'Ok' : IDL.Text, + 'Err' : BridgeIdErrors, + }); + const EntityPreviewSupportedTypes = IDL.Variant({ + 'Glb' : IDL.Null, + 'Jpg' : IDL.Null, + 'Png' : IDL.Null, + 'Gltf' : IDL.Null, + 'Other' : IDL.Text, + }); + const EntityPreview = IDL.Record({ + 'previewData' : IDL.Vec(IDL.Nat8), + 'previewType' : EntityPreviewSupportedTypes, + }); + const EntitySettings = IDL.Record({}); + const EntityTypeResourceTypes = IDL.Variant({ + 'Web' : IDL.Null, + 'DigitalAsset' : IDL.Null, + 'Content' : IDL.Null, + }); + const EntityType = IDL.Variant({ + 'Other' : IDL.Text, + 'Resource' : EntityTypeResourceTypes, + }); + const EntityInitiationObject = IDL.Record({ + 'previews' : IDL.Opt(IDL.Vec(EntityPreview)), + 'name' : IDL.Opt(IDL.Text), + 'description' : IDL.Opt(IDL.Text), + 'keywords' : IDL.Opt(IDL.Vec(IDL.Text)), + 'settings' : IDL.Opt(EntitySettings), + 'entityType' : EntityType, + 'entitySpecificFields' : IDL.Opt(IDL.Text), + }); + const EntityIdErrors = IDL.Variant({ + 'Error' : IDL.Null, + 'PreviewTooLarge' : IDL.Int, + 'EntityNotFound' : IDL.Null, + 'TooManyPreviews' : IDL.Null, + 'Unauthorized' : IDL.Null, + }); + const EntityIdResult = IDL.Variant({ + 'Ok' : IDL.Text, + 'Err' : EntityIdErrors, + }); + const Bridge = IDL.Record({ + 'id' : IDL.Text, + 'toEntityId' : IDL.Text, + 'creator' : IDL.Principal, + 'fromEntityId' : IDL.Text, + 'owner' : IDL.Principal, + 'creationTimestamp' : IDL.Nat64, + 'name' : IDL.Text, + 'description' : IDL.Text, + 'keywords' : IDL.Vec(IDL.Text), + 'settings' : BridgeSettings, + 'listOfEntitySpecificFieldKeys' : IDL.Vec(IDL.Text), + 'bridgeType' : BridgeType, + 'entitySpecificFields' : IDL.Text, + }); + const BridgeErrors = IDL.Variant({ + 'Error' : IDL.Null, + 'Unauthorized' : IDL.Text, + 'BridgeNotFound' : IDL.Null, + }); + const BridgeResult = IDL.Variant({ 'Ok' : Bridge, 'Err' : BridgeErrors }); + const Time = IDL.Int; + const BridgeLinkStatus = IDL.Variant({ + 'CreatedOther' : IDL.Null, + 'CreatedOwner' : IDL.Null, + }); + const EntityAttachedBridge = IDL.Record({ + 'id' : IDL.Text, + 'creationTime' : Time, + 'bridgeType' : BridgeType, + 'linkStatus' : BridgeLinkStatus, + }); + const EntityAttachedBridges = IDL.Vec(EntityAttachedBridge); + const Entity = IDL.Record({ + 'id' : IDL.Text, + 'creator' : IDL.Principal, + 'toIds' : EntityAttachedBridges, + 'previews' : IDL.Vec(EntityPreview), + 'owner' : IDL.Principal, + 'creationTimestamp' : IDL.Nat64, + 'name' : IDL.Text, + 'fromIds' : EntityAttachedBridges, + 'description' : IDL.Text, + 'keywords' : IDL.Vec(IDL.Text), + 'settings' : EntitySettings, + 'listOfEntitySpecificFieldKeys' : IDL.Vec(IDL.Text), + 'entityType' : EntityType, + 'entitySpecificFields' : IDL.Text, + }); + const EntityErrors = IDL.Variant({ + 'Error' : IDL.Null, + 'EntityNotFound' : IDL.Null, + 'Unauthorized' : IDL.Text, + }); + const EntityResult = IDL.Variant({ 'Ok' : Entity, 'Err' : EntityErrors }); + const EntityAttachedBridgesErrors = IDL.Variant({ + 'Error' : IDL.Null, + 'EntityNotFound' : IDL.Null, + }); + const EntityAttachedBridgesResult = IDL.Variant({ + 'Ok' : EntityAttachedBridges, + 'Err' : EntityAttachedBridgesErrors, + }); + const EntityFilterCriterion = IDL.Record({ + 'criterionKey' : IDL.Text, + 'criterionValue' : IDL.Text, + }); + const EntitiesResult = IDL.Variant({ + 'Ok' : IDL.Vec(Entity), + 'Err' : EntityErrors, + }); + const BridgeUpdateObject = IDL.Record({ + 'id' : IDL.Text, + 'name' : IDL.Opt(IDL.Text), + 'description' : IDL.Opt(IDL.Text), + 'keywords' : IDL.Opt(IDL.Vec(IDL.Text)), + 'settings' : IDL.Opt(BridgeSettings), + }); + const EntityUpdateObject = IDL.Record({ + 'id' : IDL.Text, + 'previews' : IDL.Opt(IDL.Vec(EntityPreview)), + 'name' : IDL.Opt(IDL.Text), + 'description' : IDL.Opt(IDL.Text), + 'keywords' : IDL.Opt(IDL.Vec(IDL.Text)), + 'settings' : IDL.Opt(EntitySettings), + }); + return IDL.Service({ + 'create_bridge' : IDL.Func([BridgeInitiationObject], [BridgeIdResult], []), + 'create_entity' : IDL.Func([EntityInitiationObject], [EntityIdResult], []), + 'delete_bridge' : IDL.Func([IDL.Text], [BridgeIdResult], []), + 'delete_entity' : IDL.Func([IDL.Text], [EntityIdResult], []), + 'get_bridge' : IDL.Func([IDL.Text], [BridgeResult], ['query']), + 'get_entity' : IDL.Func([IDL.Text], [EntityResult], ['query']), + 'get_from_bridge_ids_by_entity_id' : IDL.Func( + [IDL.Text], + [EntityAttachedBridgesResult], + ['query'], + ), + 'get_to_bridge_ids_by_entity_id' : IDL.Func( + [IDL.Text], + [EntityAttachedBridgesResult], + ['query'], + ), + 'match_entities' : IDL.Func( + [IDL.Vec(EntityFilterCriterion)], + [EntitiesResult], + ['query'], + ), + 'update_bridge' : IDL.Func([BridgeUpdateObject], [BridgeIdResult], []), + 'update_entity' : IDL.Func([EntityUpdateObject], [EntityIdResult], []), + }); +}; +export const init = ({ IDL }) => { return []; }; From 594133bf320aa1dfb4b3db221d69a81558c0dcf3 Mon Sep 17 00:00:00 2001 From: patnorris Date: Mon, 30 Oct 2023 21:01:20 +0000 Subject: [PATCH 07/18] Debugging Entity preview generation --- .../components/SpaceNeighbors.svelte | 8 +++++ .../helpers/bebb_utils.ts | 30 +++++++++++++++---- .../pages/CreateSpace.svelte | 10 ++++++- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte b/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte index 5b1c5dc..8476346 100644 --- a/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte +++ b/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte @@ -79,11 +79,17 @@ // Owner submitted form to create a new space neighbor const submitAddNeighborForm = async () => { + // TODO: clicking button has no effect + console.log("Debug submitAddNeighborForm"); neighborCreationInProgress = true; const spaceEntityId = extractSpaceEntityId(); + console.log("Debug submitAddNeighborForm spaceEntityId ", spaceEntityId); + console.log("Debug submitAddNeighborForm newNeighborUrl ", newNeighborUrl); + console.log("Debug submitAddNeighborForm neighborUrlInputHandler(newNeighborUrl) ", neighborUrlInputHandler(newNeighborUrl)); if (neighborUrlInputHandler(newNeighborUrl) && spaceEntityId) { // Create Neighbor connection as Bridge from Space in Bebb Protocol const spaceUrl = newNeighborUrl.replace(/\/+$/, ""); // strip any trailing slashes + console.log("Debug submitAddNeighborForm spaceUrl ", spaceUrl); const entitySpecificFields = { externalId: spaceUrl, }; @@ -101,6 +107,7 @@ } catch (error) { console.error("Error creating image preview for space: ", error); }; + console.log("Debug submitAddNeighborForm entityPreviews ", entityPreviews); const entityInitiationObject : BebbEntityInitiationObject = { settings: [], @@ -136,6 +143,7 @@ }; try { const createBebbEntityAndBridgeResponse = await createBebbEntityAndBridge(entityInitiationObject, bridgeEntityInitiationObject); + console.log("Debug submitAddNeighborForm createBebbEntityAndBridgeResponse ", createBebbEntityAndBridgeResponse); if (createBebbEntityAndBridgeResponse) { successfullyAddedNeighbor = true; } else { diff --git a/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts b/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts index 1c76a8f..35339a5 100644 --- a/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts +++ b/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts @@ -284,35 +284,45 @@ export async function getConnectedEntitiesAndBridgesInBebb(bebbEntityId: string, }; export async function getBebbEntityUrlPreview(url: string) : Promise { + console.log("Debug getBebbEntityUrlPreview url ", url); var enc = new TextEncoder(); // always utf-8 const urlSpacePreview : BebbEntityPreview = { 'previewData': enc.encode(url), 'previewType': { 'Other' : "URL" }, }; + console.log("Debug getBebbEntityUrlPreview urlSpacePreview ", urlSpacePreview); return urlSpacePreview; }; async function captureAFrameScene(spaceHtml) { + console.log("Debug captureAFrameScene spaceHtml ", spaceHtml); return new Promise(async (resolve, reject) => { // 1. Insert spaceHtml into the DOM + // TODO: disturbing UI const container = document.createElement('div'); - container.style.position = 'fixed'; - container.style.top = '-10000px'; // Offscreen + container.setAttribute("hidden", "hidden"); + //container.style.position = 'fixed'; + //container.style.top = '-10000px'; // Offscreen container.innerHTML = spaceHtml; + console.log("Debug captureAFrameScene container ", container); document.body.appendChild(container); const sceneEl = container.querySelector('a-scene'); + console.log("Debug captureAFrameScene sceneEl ", sceneEl); // Ensure A-Frame scene has loaded // @ts-ignore if (!sceneEl.hasLoaded) { await new Promise(resolve => sceneEl.addEventListener('loaded', resolve)); }; - + console.log("Debug captureAFrameScene sceneEl.hasLoaded ", sceneEl.hasLoaded); // 2. & 3. Capture the screenshot sceneEl.addEventListener('screenshotready', function(evt) { + // TODO: not triggered + console.log("Debug captureAFrameScene screenshotready"); // @ts-ignore const dataURI = evt.detail; + console.log("Debug captureAFrameScene screenshotready dataURI ", dataURI); // 4. Convert data URI to Uint8Array const byteString = atob(dataURI.split(',')[1]); @@ -324,20 +334,30 @@ async function captureAFrameScene(spaceHtml) { // Clean up and resolve the promise document.body.removeChild(container); + console.log("Debug captureAFrameScene screenshotready intArray ", intArray); resolve(intArray); }); - // @ts-ignore - sceneEl.components.screenshot.capture('perspective'); + // Wait until assets have loaded + let assetsEl = sceneEl.querySelector('a-assets'); + console.log("Debug captureAFrameScene assetsEl ", assetsEl); + setTimeout(() => { + console.log("Debug captureAFrameScene setTimeout"); + // @ts-ignore + sceneEl.components.screenshot.capture('perspective'); // TODO: downloads image to device + }, 3000); }); }; export async function getBebbEntityImagePreviewFromAframeHtml(sceneHtml: string) : Promise { + console.log("Debug getBebbEntityImagePreviewFromAframeHtml sceneHtml ", sceneHtml); // @ts-ignore const imageData : Uint8Array = await captureAFrameScene(sceneHtml); + console.log("Debug getBebbEntityImagePreviewFromAframeHtml imageData ", imageData); const imageSpacePreview : BebbEntityPreview = { 'previewData': imageData, 'previewType': { 'Jpg' : null }, }; + console.log("Debug getBebbEntityImagePreviewFromAframeHtml imageSpacePreview ", imageSpacePreview); return imageSpacePreview; }; diff --git a/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte b/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte index e4a4e4a..55b7319 100644 --- a/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte +++ b/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte @@ -158,8 +158,10 @@ }; const createSpace = async (spaceHtml) => { + console.log("Debug createSpace spaceHtml ", spaceHtml); try { const spaceResponse = await $store.backendActor.createSpace(spaceHtml); + console.log("Debug createSpace spaceResponse ", spaceResponse); // @ts-ignore if (spaceResponse && spaceResponse.Ok) { // @ts-ignore @@ -167,23 +169,27 @@ setSpaceWasCreated(); // Protocol integration: create Space as Entity in Protocol const spaceUrl = `https://${PersonalWebSpace_frontend_canister_id}${appDomain}/#/space/${spaceId}`; + console.log("Debug createSpace spaceUrl ", spaceUrl); const entitySpecificFields = { externalId: spaceUrl, }; - const entityPreviews = []; + const entityPreviews = []; + // TODO: decouple preview generation from main creation path (add to end and update Entity) try { const urlSpacePreview : BebbEntityPreview = await getBebbEntityUrlPreview(spaceUrl); entityPreviews.push(urlSpacePreview); } catch (error) { console.error("Error creating url preview for space: ", error); }; + console.log("Debug createSpace entityPreviews after getBebbEntityUrlPreview ", entityPreviews); try { const imageSpacePreview : BebbEntityPreview = await getBebbEntityImagePreviewFromAframeHtml(spaceHtml); entityPreviews.push(imageSpacePreview); } catch (error) { console.error("Error creating image preview for space: ", error); }; + console.log("Debug createSpace entityPreviews ", entityPreviews); let entityInitiationObject : BebbEntityInitiationObject = { settings: [], @@ -195,10 +201,12 @@ previews: [entityPreviews], }; const spaceEntityIdResponse = await createBebbEntity(entityInitiationObject); + console.log("Debug createSpace spaceEntityIdResponse ", spaceEntityIdResponse); // @ts-ignore if (spaceEntityIdResponse) { // @ts-ignore const spaceEntityIdUpdateResponse = await $store.backendActor.updateSpaceEntityId(spaceId, spaceEntityIdResponse); + console.log("Debug createSpace spaceEntityIdUpdateResponse ", spaceEntityIdUpdateResponse); // @ts-ignore if (!spaceEntityIdUpdateResponse || !spaceEntityIdUpdateResponse.Ok) { console.error("Update Space Error:", spaceEntityIdUpdateResponse); From 9ff2b41d7ac27f692f35a81870e998dc243ca4e1 Mon Sep 17 00:00:00 2001 From: patnorris Date: Tue, 31 Oct 2023 16:03:05 +0000 Subject: [PATCH 08/18] Debug new Entity creation with previews --- .../components/SpaceNeighbors.svelte | 7 +++-- .../pages/CreateSpace.svelte | 28 ++++++++++--------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte b/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte index 8476346..5af28e0 100644 --- a/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte +++ b/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte @@ -94,7 +94,7 @@ externalId: spaceUrl, }; - const entityPreviews = []; + const entityPreviews : Array = []; // TODO: decouple preview generation from main creation path (add to end and update Entity) try { const urlSpacePreview : BebbEntityPreview = await getBebbEntityUrlPreview(spaceUrl); entityPreviews.push(urlSpacePreview); @@ -115,8 +115,9 @@ name: [], description: [`Created as a Space Neighbor in the Open Internet Metaverse at https://${PersonalWebSpace_frontend_canister_id}${appDomain}/`] as [string], keywords: [["Space Neighbor", "Open Internet Metaverse", "Virtual Neighborhood"]] as [Array], - entitySpecificFields: [JSON.stringify(entitySpecificFields)], - previews: [entityPreviews], + entitySpecificFields: [JSON.stringify(entitySpecificFields)] as [string], + //previews: [entityPreviews] as [Array], // TODO: causes error in createBebbEntity call (invalid record) + previews: [], }; const bridgePresentationMetadata = { diff --git a/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte b/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte index 55b7319..8fc4d5b 100644 --- a/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte +++ b/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte @@ -174,7 +174,7 @@ externalId: spaceUrl, }; - const entityPreviews = []; + const entityPreviews : Array = []; // TODO: decouple preview generation from main creation path (add to end and update Entity) try { const urlSpacePreview : BebbEntityPreview = await getBebbEntityUrlPreview(spaceUrl); @@ -182,23 +182,16 @@ } catch (error) { console.error("Error creating url preview for space: ", error); }; - console.log("Debug createSpace entityPreviews after getBebbEntityUrlPreview ", entityPreviews); - try { - const imageSpacePreview : BebbEntityPreview = await getBebbEntityImagePreviewFromAframeHtml(spaceHtml); - entityPreviews.push(imageSpacePreview); - } catch (error) { - console.error("Error creating image preview for space: ", error); - }; - console.log("Debug createSpace entityPreviews ", entityPreviews); - + console.log("Debug createSpace entityPreviews after getBebbEntityUrlPreview ", entityPreviews); let entityInitiationObject : BebbEntityInitiationObject = { settings: [], entityType: { 'Resource' : { 'Web' : null } }, name: ["Personal Web Space"], description: ["Flaming Hot Personal Web Space"], keywords: [["NFT", "Space", "Open Internet Metaverse", "heeyah"]] as [Array], - entitySpecificFields: [JSON.stringify(entitySpecificFields)], - previews: [entityPreviews], + entitySpecificFields: [JSON.stringify(entitySpecificFields)] as [string], + //previews: [entityPreviews] as [Array], // TODO: causes error in createBebbEntity call (invalid record) + previews: [], }; const spaceEntityIdResponse = await createBebbEntity(entityInitiationObject); console.log("Debug createSpace spaceEntityIdResponse ", spaceEntityIdResponse); @@ -208,7 +201,16 @@ const spaceEntityIdUpdateResponse = await $store.backendActor.updateSpaceEntityId(spaceId, spaceEntityIdResponse); console.log("Debug createSpace spaceEntityIdUpdateResponse ", spaceEntityIdUpdateResponse); // @ts-ignore - if (!spaceEntityIdUpdateResponse || !spaceEntityIdUpdateResponse.Ok) { + if (spaceEntityIdUpdateResponse && spaceEntityIdUpdateResponse.Ok) { + /* try { + const imageSpacePreview : BebbEntityPreview = await getBebbEntityImagePreviewFromAframeHtml(spaceHtml); + entityPreviews.push(imageSpacePreview); + // TODO: update Entity previews + } catch (error) { + console.error("Error creating image preview for space: ", error); + }; + console.log("Debug createSpace entityPreviews ", entityPreviews); */ + } else { console.error("Update Space Error:", spaceEntityIdUpdateResponse); }; } else { From bde22d74435416828d25be05df54fae0b3c384ee Mon Sep 17 00:00:00 2001 From: patnorris Date: Fri, 3 Nov 2023 22:59:11 +0100 Subject: [PATCH 09/18] Separate update call for previews --- .../components/SpaceNeighbors.svelte | 27 ++++++++++---- .../helpers/bebb_utils.ts | 35 ++++++++++++++++--- .../pages/CreateSpace.svelte | 2 +- 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte b/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte index 5af28e0..3cbb235 100644 --- a/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte +++ b/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte @@ -5,6 +5,7 @@ BebbEntity, BebbEntityInitiationObject, BebbEntityPreview, + BebbEntityUpdateObject, } from "../helpers/bebb_utils"; import { createBebbEntityAndBridge, @@ -13,6 +14,7 @@ getConnectedEntitiesInBebb, getBebbEntityUrlPreview, getBebbEntityImagePreviewFromUrl, + updateBebbEntity, } from "../helpers/bebb_utils"; import { onMount } from "svelte"; import ProtocolEntity from "./ProtocolEntity.svelte"; @@ -101,12 +103,6 @@ } catch (error) { console.error("Error creating url preview for space: ", error); }; - try { - const imageSpacePreview : BebbEntityPreview = await getBebbEntityImagePreviewFromUrl(spaceUrl); - entityPreviews.push(imageSpacePreview); - } catch (error) { - console.error("Error creating image preview for space: ", error); - }; console.log("Debug submitAddNeighborForm entityPreviews ", entityPreviews); const entityInitiationObject : BebbEntityInitiationObject = { @@ -147,6 +143,25 @@ console.log("Debug submitAddNeighborForm createBebbEntityAndBridgeResponse ", createBebbEntityAndBridgeResponse); if (createBebbEntityAndBridgeResponse) { successfullyAddedNeighbor = true; + if (createBebbEntityAndBridgeResponse.newEntityCreated) { // The Entity did not exist already and it's thus fine to update the previews + // Add image preview to Entity (if a new Entity was created) + try { + const imageSpacePreview : BebbEntityPreview = await getBebbEntityImagePreviewFromUrl(spaceUrl); + entityPreviews.push(imageSpacePreview); + const bebbEntityUpdateObject : BebbEntityUpdateObject = { + 'id' : createBebbEntityAndBridgeResponse.entityId, + 'previews' : [entityPreviews] as [Array], + // don't update other fields (thus leave empty) + 'name' : [], + 'description' : [], + 'keywords' : [], + 'settings' : [], + }; + const updateBebbEntityResponse = await updateBebbEntity(bebbEntityUpdateObject); + } catch (error) { + console.error("Error creating image preview for space: ", error); + }; + }; } else { errorAddingNeighbor = true; }; diff --git a/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts b/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts index 35339a5..2fef8bc 100644 --- a/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts +++ b/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts @@ -11,6 +11,7 @@ import type { Entity, EntityPreview, EntityFilterCriterion, + EntityUpdateObject, } from "src/integrations/BebbProtocol/bebb.did"; export type BebbEntity = Entity; @@ -23,6 +24,7 @@ export type BebbBridge = Bridge; export type BebbEntityAndBridge = { entity: BebbEntity, bridge: BebbBridge }; export type BebbEntityPreview = EntityPreview; export type BebbEntityFilterCriterion = EntityFilterCriterion; +export type BebbEntityUpdateObject = EntityUpdateObject; let appStore; store.subscribe((value) => appStore = value); @@ -40,6 +42,19 @@ export async function createBebbEntity(entityInitiationObject: BebbEntityInitiat }; }; +export async function updateBebbEntity(entityUpdateObject: BebbEntityUpdateObject) { + if (!appStore) { + throw new Error("Error in updateBebbEntity: store not initialized"); + }; + const updateEntityResponse = await appStore.protocolActor.update_entity(entityUpdateObject); + // @ts-ignore + if (updateEntityResponse && updateEntityResponse.Ok) { + return updateEntityResponse.Ok; + } else { + throw new Error("Error updating Entity"); + }; +}; + export async function createBebbBridge(bridgeEntityInitiationObject: BebbBridgeInitiationObject) { if (!appStore) { throw new Error("Error in createBebbBridge: store not initialized"); @@ -53,6 +68,8 @@ export async function createBebbBridge(bridgeEntityInitiationObject: BebbBridgeI }; }; +// TODO: updateBebbBridge + export async function createBebbEntityIfNonExistent(entityInitiationObject: BebbEntityInitiationObject) { if (!appStore) { throw new Error("Error in createBebbEntityIfNonExistent: store not initialized"); @@ -70,11 +87,17 @@ export async function createBebbEntityIfNonExistent(entityInitiationObject: Bebb // Check if any Entities matched the filter criteria if (matchResult && matchResult.Ok && matchResult.Ok.length > 0) { // Assuming the first matched Entity is the correct one (and there are no duplicates) - return matchResult.Ok[0].id; // Return the id of the existing Entity + return { + entityId: matchResult.Ok[0].id, // Return the id of the existing Entity + newEntityCreated: false, + }; }; // Entity does not exist, so create it - return createBebbEntity(entityInitiationObject); + return { + entityId: await createBebbEntity(entityInitiationObject), + newEntityCreated: true, + }; } @@ -86,7 +109,7 @@ export async function createBebbEntityAndBridge(entityInitiationObject: BebbEnti // @ts-ignore if (createEntityResponse) { // @ts-ignore - const newNeighborEntityId = createEntityResponse; + const newNeighborEntityId = createEntityResponse.entityId; if (!bridgeEntityInitiationObject.toEntityId || bridgeEntityInitiationObject.toEntityId === "") { bridgeEntityInitiationObject.toEntityId = newNeighborEntityId; } else { @@ -95,7 +118,11 @@ export async function createBebbEntityAndBridge(entityInitiationObject: BebbEnti const createBridgeResponse = await createBebbBridge(bridgeEntityInitiationObject); // @ts-ignore if (createBridgeResponse) { - return true; + return { + entityId: newNeighborEntityId, + bridgeId: createBridgeResponse, + newEntityCreated: createEntityResponse.newEntityCreated, + }; } else { throw new Error("Error creating new Bridge"); }; diff --git a/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte b/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte index 8fc4d5b..e1c8c17 100644 --- a/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte +++ b/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte @@ -205,7 +205,7 @@ /* try { const imageSpacePreview : BebbEntityPreview = await getBebbEntityImagePreviewFromAframeHtml(spaceHtml); entityPreviews.push(imageSpacePreview); - // TODO: update Entity previews + // TODO: update Entity with previews } catch (error) { console.error("Error creating image preview for space: ", error); }; From 320612346b4723a4132ca35d7b23fcbc9be57df8 Mon Sep 17 00:00:00 2001 From: patnorris Date: Tue, 7 Nov 2023 16:02:48 +0100 Subject: [PATCH 10/18] Update Entity preview --- .../components/SpaceNeighbors.svelte | 2 +- .../pages/CreateSpace.svelte | 26 +++++++++++++------ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte b/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte index 3cbb235..8ffa04c 100644 --- a/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte +++ b/src/PersonalWebSpace_frontend/components/SpaceNeighbors.svelte @@ -96,7 +96,7 @@ externalId: spaceUrl, }; - const entityPreviews : Array = []; // TODO: decouple preview generation from main creation path (add to end and update Entity) + const entityPreviews : Array = []; try { const urlSpacePreview : BebbEntityPreview = await getBebbEntityUrlPreview(spaceUrl); entityPreviews.push(urlSpacePreview); diff --git a/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte b/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte index e1c8c17..ade0b3b 100644 --- a/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte +++ b/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte @@ -14,11 +14,13 @@ import type { BebbEntityInitiationObject, BebbEntityPreview, + BebbEntityUpdateObject, } from "../helpers/bebb_utils"; import { createBebbEntity, getBebbEntityUrlPreview, getBebbEntityImagePreviewFromAframeHtml, + updateBebbEntity, } from "../helpers/bebb_utils"; let webHostedGlbModelUrl : string = ""; @@ -174,8 +176,7 @@ externalId: spaceUrl, }; - const entityPreviews : Array = []; - // TODO: decouple preview generation from main creation path (add to end and update Entity) + const entityPreviews : Array = []; try { const urlSpacePreview : BebbEntityPreview = await getBebbEntityUrlPreview(spaceUrl); entityPreviews.push(urlSpacePreview); @@ -202,25 +203,34 @@ console.log("Debug createSpace spaceEntityIdUpdateResponse ", spaceEntityIdUpdateResponse); // @ts-ignore if (spaceEntityIdUpdateResponse && spaceEntityIdUpdateResponse.Ok) { - /* try { + // Add image preview to Entity (if a new Entity was created) + try { const imageSpacePreview : BebbEntityPreview = await getBebbEntityImagePreviewFromAframeHtml(spaceHtml); entityPreviews.push(imageSpacePreview); - // TODO: update Entity with previews + const bebbEntityUpdateObject : BebbEntityUpdateObject = { + 'id' : spaceEntityIdResponse, + 'previews' : [entityPreviews] as [Array], + // don't update other fields (thus leave empty) + 'name' : [], + 'description' : [], + 'keywords' : [], + 'settings' : [], + }; + const updateBebbEntityResponse = await updateBebbEntity(bebbEntityUpdateObject); } catch (error) { console.error("Error creating image preview for space: ", error); }; - console.log("Debug createSpace entityPreviews ", entityPreviews); */ } else { - console.error("Update Space Error:", spaceEntityIdUpdateResponse); + console.error("Update Space Error: ", spaceEntityIdUpdateResponse); }; } else { - console.error("Create Entity Error:", spaceEntityIdResponse); + console.error("Create Entity Error: ", spaceEntityIdResponse); }; } else { console.error("Create Space Error:", spaceResponse); }; } catch (error) { - console.error("Create Space Error:", error); + console.error("Create Space Error: ", error); }; }; From de9c6c482d2094785e21e9edc616dbae222d5de3 Mon Sep 17 00:00:00 2001 From: patnorris Date: Wed, 8 Nov 2023 20:01:11 +0100 Subject: [PATCH 11/18] Capture and store image preview --- .../helpers/bebb_utils.ts | 100 ++++++++++++------ .../pages/CreateSpace.svelte | 2 +- 2 files changed, 68 insertions(+), 34 deletions(-) diff --git a/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts b/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts index 2fef8bc..914c864 100644 --- a/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts +++ b/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts @@ -43,10 +43,12 @@ export async function createBebbEntity(entityInitiationObject: BebbEntityInitiat }; export async function updateBebbEntity(entityUpdateObject: BebbEntityUpdateObject) { + console.log("Debug updateBebbEntity entityUpdateObject ", entityUpdateObject); if (!appStore) { throw new Error("Error in updateBebbEntity: store not initialized"); }; const updateEntityResponse = await appStore.protocolActor.update_entity(entityUpdateObject); + console.log("Debug updateBebbEntity updateEntityResponse ", updateEntityResponse); // @ts-ignore if (updateEntityResponse && updateEntityResponse.Ok) { return updateEntityResponse.Ok; @@ -311,20 +313,64 @@ export async function getConnectedEntitiesAndBridgesInBebb(bebbEntityId: string, }; export async function getBebbEntityUrlPreview(url: string) : Promise { - console.log("Debug getBebbEntityUrlPreview url ", url); var enc = new TextEncoder(); // always utf-8 const urlSpacePreview : BebbEntityPreview = { 'previewData': enc.encode(url), 'previewType': { 'Other' : "URL" }, }; - console.log("Debug getBebbEntityUrlPreview urlSpacePreview ", urlSpacePreview); return urlSpacePreview; }; +// Convert the Blob to an ArrayBuffer +const blobToArrayBuffer = (blob) => { + return blob.arrayBuffer(); +}; + +// Convert the ArrayBuffer to a Uint8Array +const arrayBufferToUint8Array = (buffer) => { + return new Uint8Array(buffer); +}; + +// Putting it all together +const getUint8ArrayFromCanvas = async (canvas) => { + try { + const blob = await canvasToBlob(canvas); + const buffer = await blobToArrayBuffer(blob); + const uint8Array = arrayBufferToUint8Array(buffer); + return uint8Array; // This is the Uint8Array representation of your canvas + } catch (error) { + console.error(error); + return null; + } +}; + +function displayImageInPopup(screenshotArray) { + // Create a Blob from the Uint8Array + const blob = new Blob([screenshotArray], { type: 'image/jpeg' }); + + // Create an Object URL for the blob + const imageUrl = URL.createObjectURL(blob); + console.log("Debug captureAFrameScene imageUrl ", imageUrl); + + // Open a new popup window + const popup = window.open('', 'Image Preview', 'width=600,height=400'); + + // Check if the popup was successfully opened + if (popup) { + console.log("Debug captureAFrameScene popup"); + // Write the HTML content for the new window + popup.document.write(`Image Preview`); + + // Close the document to apply the content + popup.document.close(); + } else { + console.log('Popup blocked or failed to open.'); + }; +}; + async function captureAFrameScene(spaceHtml) { - console.log("Debug captureAFrameScene spaceHtml ", spaceHtml); + console.log("Debug captureAFrameScene"); return new Promise(async (resolve, reject) => { - // 1. Insert spaceHtml into the DOM // TODO: disturbing UI const container = document.createElement('div'); container.setAttribute("hidden", "hidden"); @@ -335,7 +381,6 @@ async function captureAFrameScene(spaceHtml) { document.body.appendChild(container); const sceneEl = container.querySelector('a-scene'); - console.log("Debug captureAFrameScene sceneEl ", sceneEl); // Ensure A-Frame scene has loaded // @ts-ignore @@ -343,42 +388,31 @@ async function captureAFrameScene(spaceHtml) { await new Promise(resolve => sceneEl.addEventListener('loaded', resolve)); }; console.log("Debug captureAFrameScene sceneEl.hasLoaded ", sceneEl.hasLoaded); - // 2. & 3. Capture the screenshot - sceneEl.addEventListener('screenshotready', function(evt) { - // TODO: not triggered - console.log("Debug captureAFrameScene screenshotready"); - // @ts-ignore - const dataURI = evt.detail; - console.log("Debug captureAFrameScene screenshotready dataURI ", dataURI); - - // 4. Convert data URI to Uint8Array - const byteString = atob(dataURI.split(',')[1]); - const arrayBuffer = new ArrayBuffer(byteString.length); - const intArray = new Uint8Array(arrayBuffer); - for (let i = 0; i < byteString.length; i++) { - intArray[i] = byteString.charCodeAt(i); - }; - - // Clean up and resolve the promise - document.body.removeChild(container); - console.log("Debug captureAFrameScene screenshotready intArray ", intArray); - resolve(intArray); - }); // Wait until assets have loaded let assetsEl = sceneEl.querySelector('a-assets'); console.log("Debug captureAFrameScene assetsEl ", assetsEl); - setTimeout(() => { - console.log("Debug captureAFrameScene setTimeout"); - // @ts-ignore - sceneEl.components.screenshot.capture('perspective'); // TODO: downloads image to device - }, 3000); + await new Promise(resolve => + setTimeout(() => { + console.log("Debug captureAFrameScene setTimeout"); + resolve(""); + }, 3000) + ); + // @ts-ignore + const screenshotCanvas = sceneEl.components.screenshot.getCanvas('perspective'); + console.log("Debug captureAFrameScene screenshotCanvas ", screenshotCanvas); + const screenshotArray = await getUint8ArrayFromCanvas(screenshotCanvas); + console.log("Debug captureAFrameScene screenshotArray ", screenshotArray); + + document.body.removeChild(container); + + resolve(screenshotArray); }); }; export async function getBebbEntityImagePreviewFromAframeHtml(sceneHtml: string) : Promise { - console.log("Debug getBebbEntityImagePreviewFromAframeHtml sceneHtml ", sceneHtml); + console.log("Debug getBebbEntityImagePreviewFromAframeHtml"); // @ts-ignore - const imageData : Uint8Array = await captureAFrameScene(sceneHtml); + const imageData : Uint8Array = await captureAFrameScene(sceneHtml); console.log("Debug getBebbEntityImagePreviewFromAframeHtml imageData ", imageData); const imageSpacePreview : BebbEntityPreview = { 'previewData': imageData, diff --git a/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte b/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte index ade0b3b..6ef0cc3 100644 --- a/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte +++ b/src/PersonalWebSpace_frontend/pages/CreateSpace.svelte @@ -160,7 +160,6 @@ }; const createSpace = async (spaceHtml) => { - console.log("Debug createSpace spaceHtml ", spaceHtml); try { const spaceResponse = await $store.backendActor.createSpace(spaceHtml); console.log("Debug createSpace spaceResponse ", spaceResponse); @@ -206,6 +205,7 @@ // Add image preview to Entity (if a new Entity was created) try { const imageSpacePreview : BebbEntityPreview = await getBebbEntityImagePreviewFromAframeHtml(spaceHtml); + console.log("Debug createSpace imageSpacePreview ", imageSpacePreview); entityPreviews.push(imageSpacePreview); const bebbEntityUpdateObject : BebbEntityUpdateObject = { 'id' : spaceEntityIdResponse, From b74c675c72b4dd7ee622a40f20eaa0d52304717e Mon Sep 17 00:00:00 2001 From: patnorris Date: Mon, 13 Nov 2023 22:44:25 +0100 Subject: [PATCH 12/18] Debug image preview UI disruption --- .../helpers/bebb_utils.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts b/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts index 914c864..e52a1eb 100644 --- a/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts +++ b/src/PersonalWebSpace_frontend/helpers/bebb_utils.ts @@ -371,9 +371,18 @@ function displayImageInPopup(screenshotArray) { async function captureAFrameScene(spaceHtml) { console.log("Debug captureAFrameScene"); return new Promise(async (resolve, reject) => { + // Store the original overflow value +const originalOverflow = document.body.style.overflow; + +// Set overflow to auto +document.body.style.overflow = 'auto'; // TODO: disturbing UI const container = document.createElement('div'); - container.setAttribute("hidden", "hidden"); + //container.setAttribute("hidden", "hidden"); + //container.style.display = 'none'; // Hide the container + container.style.visibility = "hidden"; + container.style.width = '10%'; + container.style.height = '10%'; //container.style.position = 'fixed'; //container.style.top = '-10000px'; // Offscreen container.innerHTML = spaceHtml; @@ -402,8 +411,11 @@ async function captureAFrameScene(spaceHtml) { console.log("Debug captureAFrameScene screenshotCanvas ", screenshotCanvas); const screenshotArray = await getUint8ArrayFromCanvas(screenshotCanvas); console.log("Debug captureAFrameScene screenshotArray ", screenshotArray); + displayImageInPopup(screenshotArray); document.body.removeChild(container); + // Restore the original overflow value +document.body.style.overflow = originalOverflow; resolve(screenshotArray); }); From f0191d715e85a3fd0c701fdf653121e448287daa Mon Sep 17 00:00:00 2001 From: patnorris Date: Wed, 15 Nov 2023 17:48:03 +0100 Subject: [PATCH 13/18] Add working image preview functionality --- .../components/GlbModelPreview.svelte | 2 +- .../components/MediaContentPreview.svelte | 2 +- .../helpers/bebb_utils.ts | 73 +++++++++++++++---- .../pages/CreateSpace.svelte | 68 ++++++++++------- 4 files changed, 104 insertions(+), 41 deletions(-) diff --git a/src/PersonalWebSpace_frontend/components/GlbModelPreview.svelte b/src/PersonalWebSpace_frontend/components/GlbModelPreview.svelte index 9d0d555..b1a2656 100644 --- a/src/PersonalWebSpace_frontend/components/GlbModelPreview.svelte +++ b/src/PersonalWebSpace_frontend/components/GlbModelPreview.svelte @@ -11,7 +11,7 @@ : getStringForSpaceFromUserUploadedModel();
- +