Skip to content

Commit

Permalink
Merge pull request #3904 from mozilla/feature/link-thumbnails
Browse files Browse the repository at this point in the history
Add link behavior for images and videos
  • Loading branch information
robertlong authored Feb 16, 2021
2 parents 0812729 + 82b845f commit bb0efe1
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 17 deletions.
5 changes: 5 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
]
},
"dependencies": {
"@braintree/sanitize-url": "^5.0.0",
"@formatjs/intl-locale": "^2.4.13",
"@formatjs/intl-pluralrules": "^4.0.3",
"@formatjs/intl-relativetimeformat": "^8.0.1",
Expand Down
2 changes: 2 additions & 0 deletions src/components/media-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,8 @@ AFRAME.registerComponent("media-loader", {
template: "#photo-hover-menu",
isFlat: true
});
} else if (this.data.mediaOptions.href) {
this.el.setAttribute("hover-menu__link", { template: "#link-hover-menu", isFlat: true });
}
},
{ once: true }
Expand Down
6 changes: 5 additions & 1 deletion src/components/media-views.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ AFRAME.registerComponent("media-video", {
this.snapButton = this.el.querySelector(".video-snap-button");
this.timeLabel = this.el.querySelector(".video-time-label");
this.volumeLabel = this.el.querySelector(".video-volume-label");
this.linkButton = this.el.querySelector(".video-link-button");

this.playPauseButton.object3D.addEventListener("interact", this.togglePlaying);
this.seekForwardButton.object3D.addEventListener("interact", this.seekForward);
Expand Down Expand Up @@ -858,7 +859,8 @@ AFRAME.registerComponent("media-video", {
updateHoverMenu() {
if (!this.hoverMenu) return;

const pinnableElement = this.el.components["media-loader"].data.linkedEl || this.el;
const mediaLoader = this.el.components["media-loader"].data;
const pinnableElement = mediaLoader.linkedEl || this.el;
const isPinned = pinnableElement.components.pinnable && pinnableElement.components.pinnable.data.pinned;
this.playbackControls.object3D.visible = !this.data.hidePlaybackControls && !!this.video;
this.timeLabel.object3D.visible = !this.data.hidePlaybackControls;
Expand All @@ -872,6 +874,8 @@ AFRAME.registerComponent("media-video", {

this.playPauseButton.object3D.visible = this.seekForwardButton.object3D.visible = this.seekBackButton.object3D.visible = mayModifyPlayHead;

this.linkButton.object3D.visible = !!mediaLoader.mediaOptions.href;

if (this.videoIsLive) {
this.timeLabel.setAttribute("text", "value", "LIVE");
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/open-media-button.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ AFRAME.registerComponent("open-media-button", {

this.updateSrc = async () => {
if (!this.targetEl.parentNode) return; // If removed
const src = (this.src = this.targetEl.components["media-loader"].data.src);
const mediaLoader = this.targetEl.components["media-loader"].data;
const src = (this.src = (mediaLoader.mediaOptions && mediaLoader.mediaOptions.href) || mediaLoader.src);
const visible = src && guessContentType(src) !== "video/vnd.hubs-webrtc";
const mayChangeScene = this.el.sceneEl.systems.permissions.canOrWillIfCreator("update_hub");

Expand Down
25 changes: 19 additions & 6 deletions src/gltf-component-mappings.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { sanitizeUrl } from "@braintree/sanitize-url";
import "./components/gltf-model-plus";
import { getSanitizedComponentMapping } from "./utils/component-mappings";
import { TYPE, SHAPE, FIT } from "three-ammo/constants";
Expand Down Expand Up @@ -178,7 +179,7 @@ AFRAME.GLTFModelPlus.registerComponent("media", "media", (el, componentName, com
}

const mediaLoaderAttributes = {
src: componentData.src,
src: sanitizeUrl(componentData.src),
fitToBox: componentData.contentSubtype ? false : true,
resolve: true,
fileIsOwned: true,
Expand Down Expand Up @@ -209,11 +210,17 @@ AFRAME.GLTFModelPlus.registerComponent("media", "media", (el, componentName, com
async function mediaInflator(el, componentName, componentData, components) {
let isControlled = true;

if (componentName === "link" && (components.video || components.image)) {
// video/image component will set link url specified in link component.
return;
}

if (components.networked) {
isControlled = componentData.controls || componentName === "link";

const hasVolume = componentName === "video" || componentName === "audio";
const templateName = isControlled || hasVolume ? "#static-controlled-media" : "#static-media";
const templateName =
componentName === "model" || isControlled || hasVolume ? "#static-controlled-media" : "#static-media";

el.setAttribute("networked", {
template: templateName,
Expand Down Expand Up @@ -251,18 +258,24 @@ async function mediaInflator(el, componentName, componentData, components) {
el.setAttribute("video-pause-state", { paused: mediaOptions.videoPaused });
}

if ((componentName === "video" || componentName === "image") && components.link) {
mediaOptions.href = sanitizeUrl(components.link.href);
}

const src = componentName === "link" ? componentData.href : componentData.src;

el.setAttribute("media-loader", {
src,
src: sanitizeUrl(src),
fitToBox: true,
resolve: true,
fileIsOwned: true,
animate: false,
mediaOptions
mediaOptions,
moveTheParentNotTheMesh: true
});
}

AFRAME.GLTFModelPlus.registerComponent("model", "model", mediaInflator);
AFRAME.GLTFModelPlus.registerComponent("image", "image", mediaInflator);
AFRAME.GLTFModelPlus.registerComponent("audio", "audio", mediaInflator, (name, property, value) => {
if (property === "paused") {
Expand All @@ -287,15 +300,15 @@ AFRAME.GLTFModelPlus.registerComponent("hoverable", "is-remote-hover-target", el

AFRAME.GLTFModelPlus.registerComponent("spawner", "spawner", (el, componentName, componentData) => {
el.setAttribute("media-loader", {
src: componentData.src,
src: sanitizeUrl(componentData.src),
resolve: true,
fileIsOwned: true,
animate: false,
moveTheParentNotTheMesh: true
});
el.setAttribute("css-class", "interactable");
el.setAttribute("super-spawner", {
src: componentData.src,
src: sanitizeUrl(componentData.src),
resolve: true,
template: "#interactable-media",
mediaOptions: componentData.mediaOptions || {}
Expand Down
10 changes: 4 additions & 6 deletions src/hub.html
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,9 @@
visible="false"
></a-entity>
</a-entity>
<a-entity class="ui video-link-button" visible="false" mixin="rounded-text-action-button ui" is-remote-hover-target tags="singleActionButton: true; isHoverMenuChild: true;" open-media-button scale="0.8 0.8 0.8" position="0 -0.300 0.001">
<a-entity text="value:open link; width:1.5; align:center;" text-raycast-hack position="0 0 0.02"></a-entity>
</a-entity>
</a-entity>
</template>

Expand All @@ -932,12 +935,7 @@

<template id="link-hover-menu">
<a-entity class="ui interactable-ui hover-container" visible="false">
<a-entity mixin="rounded-text-button ui"
is-remote-hover-target tags="singleActionButton: true;
isHoverMenuChild: true;" scale="0.8 0.8 0.8" refresh-media-button position="0 0.125 0.001">
<a-entity text="value:refresh; width:1.5; align:center;" text-raycast-hack position="0 0 0.02"></a-entity>
</a-entity>
<a-entity mixin="rounded-text-action-button ui" is-remote-hover-target tags="singleActionButton: true; isHoverMenuChild: true;" open-media-button position="0 -0.125 0.001">
<a-entity mixin="rounded-text-action-button ui" is-remote-hover-target tags="singleActionButton: true; isHoverMenuChild: true;" open-media-button position="0 0 0.001">
<a-entity text="value:open link; width:1.5; align:center;" text-raycast-hack position="0 0 0.02"></a-entity>
</a-entity>
</a-entity>
Expand Down
7 changes: 5 additions & 2 deletions src/react-components/room/object-hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ export function isPlayer(object) {
export function getObjectUrl(object) {
const mediaLoader = object.el.components["media-loader"];

if (mediaLoader && mediaLoader.data.src && !mediaLoader.data.src.startsWith("hubs://")) {
return mediaLoader.data.src;
const url =
mediaLoader && ((mediaLoader.data.mediaOptions && mediaLoader.data.mediaOptions.href) || mediaLoader.data.src);

if (url && !url.startsWith("hubs://")) {
return url;
}

return null;
Expand Down
2 changes: 1 addition & 1 deletion src/systems/hubs-systems.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ AFRAME.registerSystem("hubs-systems", {
this.emojiSystem.tick(t, systems.userinput);
this.cursorPoseTrackingSystem.tick();
this.cursorTargettingSystem.tick(t);
this.hoverMenuSystem.tick();
this.positionAtBorderSystem.tick();
this.scaleInScreenSpaceSystem.tick();
this.constraintsSystem.tick();
Expand All @@ -95,7 +96,6 @@ AFRAME.registerSystem("hubs-systems", {
this.holdableButtonSystem.tick();
this.hoverButtonSystem.tick();
this.drawingMenuSystem.tick();
this.hoverMenuSystem.tick();
this.hapticFeedbackSystem.tick(
this.twoPointStretchingSystem,
this.singleActionButtonSystem.didInteractLeftThisFrame,
Expand Down

0 comments on commit bb0efe1

Please sign in to comment.