I'm trying to add admob to my app with "nativescript-admob", here is the code i have for now :
<template>
<Page class="page">
<StackLayout class="hello-world">
<Label text="my home page"/>
</StackLayout>
</Page>
</template>
<script>
const admob = require("nativescript-admob");
export default {
mounted() {
admob.createBanner({
// if this 'view' property is not set, the banner is overlayed on the current top most view
// view: ..,
testing: true, // set to false to get real banners
size: admob.AD_SIZE.SMART_BANNER, // anything in admob.AD_SIZE, like admob.AD_SIZE.SMART_BANNER
androidBannerId: "ca-app-pub-AAAAAAAAAAA/AAAAAAAAA", // add your own
margins: {
// if both are set, top wins
//top: 10
bottom: 50
},
}).then(
function() {
console.log("admob createBanner done");
},
function(error) {
console.log("admob createBanner error: " + error);
}
)
},
}
</script>
i try to launch the admob on "mounted" but i cant make it work, does anyone integrated admob this way with nativescript-vue ? in my case i don't even see the log "admob createBanner done" log so maybe i don't use this plugin well.
the admob.createBanner() function has to be surrounded by a setTimeout() to launch after, it seems it has to be launch when a page is fully loaded. thx for the help of the slack nativescript-vue channel contributors !
Related
What I have
I have made use of IntersectionObserver on my feed page. It behaves like TikTok. Scroll up or down to see the next video. On enter the video plays. On exit, it stops playing.
The Problem
It works on Android and Windows perfectly. On iOS, not so much. The videos are not autoplaying as expected. A bit strange though, is if I click the video (which calls play() on that video), and then scroll it out of view, the video does stop. When I scroll it back into view, it auto plays again. So I know that IntersectionObserver is being recognized, just not triggered initially.
The Code
==================================
The Feed Page, where the Observer is being instantiated:
data() {
return {
observer: null,
}
};
mounted() {
let config = { threshold: 0.1 };
if (process.client) {
if (/iPhone|iPad/i.test(navigator.userAgent)) {
config.root = null;
}
}
this.observer = new IntersectionObserver(function (entries) {
entries.forEach(({ target, isIntersecting }) => {
if (isIntersecting) {
target.play();
} else {
target.pause();
target.currentTime = 0;
}
});
}, config);
beforeDestroy() {
this.observer.disconnect();
},
HTML
<div
v-for="(post, index) in posts"
:key="index"
>
<MobileFeedItem :post="post" :observer="observer" />
</div>
=================================
The MobileFeedItem component
props: ["post", "observer"],
mounted() {
this.$nextTick(() => {
if (this.observer !== null && this.checkMediaTypeIsVideo(this.post)) {
this.observer.observe(
document.getElementById(
`video_${this.getContentId(this.post)}_mobile`
)
);
}
});
HTML
<video
:id="`video_${getContentId(post)}_mobile`"
:data-poster="getThumbnail(post)"
preload="none"
disablePictureInPicture
crossorigin
loop
playsinline
v-lazy-load
class="w-full h-full my-4"
>
<source :data-src="getMedia(post)" type="video/mp4" />
</video>
My Thoughts...
The observer is being instantiated and recognized, just not triggered. So is there a way that I can force the browser to wake up and become aware of the observer without having to click on each of the video elements first?
I found the answer. It wasn't anything wrong with the IntersectionObserver, but because my video was not muted.
"By default, autoplay executes only if the video doesn’t contain an audio track, or if the video element includes the muted attribute. Video playback pauses if the element gains an audio track, becomes unmuted without user interaction, or if the video is no longer onscreen"
source - https://developer.apple.com/documentation/webkit/delivering_video_content_for_safari
It also appears that we don't need intersection observer at all for Safari, as it does this for us. Huh.
Does anyone know how can I show the property pane without creating webpart?
I want to show the property pane after clicking the User Management icon, which is created with extension
Taken from this repo which has some of the official samples from the SPFx extensions model and depicts a pretty close use-case to the one that you are searching, there is an element in Fluent UI called Panel.
As it is written in the documentation:
Panels are overlays that contain supplementary content and are used for complex creation, edit, or management experiences. For example, viewing details about an item in a list or editing settings.
Furthermore, scouring the repo we can see that the panel is triggered:
...
import { Panel, PanelType } from "office-ui-fabric-react/lib/Panel";
...
class GraphBot extends React.Component<IGraphBotProps, IGraphBotState> {
....
public render() {
// Be careful, the user Id is mandatory to be able to use the bot state service (i.e privateConversationData)
return (
<div className={ styles.banner }>
<ActionButton onClick= { this._login } checked={ true } iconProps={ { iconName: "Robot", className: styles.banner__chatButtonIcon } } className={ styles.banner__chatButton}>
{ strings.GraphBotButtonLabel }
</ActionButton>
<Panel
isOpen={ this.state.showPanel }
type={ PanelType.medium}
isLightDismiss={ true }
onDismiss={ () => this.setState({ showPanel: false }) }
>
{ this.state.isBotInitializing ?
....
}
</Panel>
</div>
);
}
There is an <ActionButton> with an OnClick Eventhandler to execute the below function :
private async _login() {
this.setState({
isBotInitializing :true,
showPanel: true,
});
....
The above function sets the showPanel prop to true and this prop is used in the Panel Component, where it checks when set to true to open the Panel and move on with the Business Logic of the application extension.
The same can be seen in the Fluent UI Documentation here, in the basic example.
import * as React from 'react';
import { DefaultButton } from '#fluentui/react/lib/Button';
import { Panel } from '#fluentui/react/lib/Panel';
import { useBoolean } from '#fluentui/react-hooks';
export const PanelBasicExample: React.FunctionComponent = () => {
const [isOpen, { setTrue: openPanel, setFalse: dismissPanel }] = useBoolean(false);
return (
<div>
<DefaultButton text="Open panel" onClick={openPanel} />
<Panel
headerText="Sample panel"
isOpen={isOpen}
onDismiss={dismissPanel}
// You MUST provide this prop! Otherwise screen readers will just say "button" with no label.
closeButtonAriaLabel="Close"
>
<p>Content goes here.</p>
</Panel>
</div>
);
};
I am trying to use image as background using tailwind css in Create react app. But can't figure out how to add background image class.
The error:
Module not found: Error: Can't resolve './src/images/pages/login.svg' in 'C:<some_project>\src'
what i tried:
backgroundImage: {
"login-image": "url('./src/images/pages/login.svg')",
},
// assumed it starts from src
backgroundImage: {
"login-image": "url('/images/pages/login.svg')",
},
// also tried to place it into public page and include like
backgroundImage: {
"login-image": "url('/images/pages/login.svg')",
},
Any help would be appreciated! Thanks
This is how I got mine to work:
In the tailwind.config.js, I added my background to extend (make sure to put your appropriate image url):
extend: {
backgroundImage: {
awlogo: "url('./images/aw-lg-logo.png')",
awOpac: "url('./images/awopac.png')"
},
},
Here is my App.js example:
import "./index.css";
function App() {
return (
<div className="grid place-items-center h-screen bg-blue">
<img
className="bg-no-repeat w-screen h-screen opacity-5 fixed overflow-hidden z-1 bg-cover bg-awOpac "
alt="aw logo opacity"
/>
</div>
);
}
where it says bg-awOpac that basically says:
.bg-awOpac {
background-image: url('./images/awopac.png');
}
Make sure you are giving the image a height and width as well.
I am using "tailwindcss": "^3.0.23"
I have a scene where I am changing the src for sky using buttons I created "outside the scene". Currently everything works fine but I would like to show a preloader while waiting for the next image to load.
Here you can see my scene: http://scriptstrainer.com/vr_training/
Below I have provided some of my code:
<a-scene>
<a-sky src="images/0-1.jpg" id="img-src">
</a-scene>
<div>
<img src="images/t1.png">
</div>
<div>
<img src="images/t2.png">
</div>
<div>
<img src="images/t3.png">
</div>
<script>
var sky = document.querySelector('#img-src');
var button1 = document.querySelector('#button1');
var button2 = document.querySelector('#button2');
var button3 = document.querySelector('#button3');
button1.addEventListener('click', function() {
sky.setAttribute('src', 'images/0-1.jpg');
});
button2.addEventListener('click', function() {
sky.setAttribute('src', 'images/2.JPG');
});
button3.addEventListener('click', function() {
sky.setAttribute('src', 'images/3.JPG');
});
</script>
Thanks for your assistance...
https://aframe.io/docs/0.4.0/components/material.html#events_materialtextureloaded
There's an event materialtextureloaded you can use to detect when the texture has loaded onto the mesh. In between the time you request to set the texture and the time the texture is set, you can display a loading graphic.
button1.addEventListener('click', function() {
sky.setAttribute('src', 'images/0-1.jpg');
// Display something in the meantime.
sky.addEventListener('materialtextureloaded', function () {
// Small timeout just in case?
setTimeout(function () { // Remove the placeholder. }, 100);
});
});
The loading graphic can be like a spinning object in the scene, a fade-in black mask around the camera (as used in https://github.com/aframevr/360-image-gallery-boilerplate). It depends on what you want it to be.
I had the same scenario where I wanted to add a preloader and only when the image is displayed, to remove the preloader.
I tried using events 'load' and 'loaded' but didn't work as I found out images are not displayed once they finish loading.
Eventually I got help from the AFrame GitHub page and that's how I did it:
<a-assets>
<img id='img-src' src='image.jpg'/>
</a-assets>
<a-sky src='#img-src' id='sky-id'></a-sky>
<script type='text/javascript'>
var skyEl = document.querySelector('#sky-id');
function loaded()
{
var preloader = document.querySelector('#preloader');
preloader.style.display = "none";
}
skyEl.addEventListener('materialtextureloaded', loaded);
</script>
I'm trying to use Magnific Popup in collaboration with elevateZoom, I have it working to a point where I have bound a click handler to the zoom container, which in this case is the .product-image-gallery div.
If I pass a single image src, e.g. $j('.product-image-gallery .gallery-image').attr('src'); as the src: argument then I get a popup with an image, but as soon as I pass a more general selector such as the .gallery-image on its own, i get a 'The image could not be loaded' message.
The aim is to have the popup let me cycle through all the avaliable product images.
HTML:
<div class="product-image-gallery">
<img id="image-main" class="gallery-image visible" src="example1.jpg" alt="Title" title="Title" />
<img id="image-0" class="gallery-image" src="example1.jpg" data-zoom-image="example1.jpg" />
<img id="image-1" class="gallery-image" src="example2.jpg" data-zoom-image="example2.jpg" />
<img id="image-2" class="gallery-image" src="example3.jpg" data-zoom-image="example3.jpg" />
</div>
JS ($j because jQuery is in noConflict mode):
$j.magnificPopup.open({
items: {
src: '.gallery-image',
type: 'image',
gallery: {
enabled: true
}
}
});
I ended up building an object then passing that to magnific-popup, my solution:
$j('.product-image-gallery').bind('click', function(){
galleryObj = [];
$j('.product-image-gallery .gallery-image').not('#image-main').each(function() {
var src = $j(this).data('zoom-image'),
type = 'image'; // it's always an image :)
image = {};
image ["src"] = src;
image ["type"] = type;
galleryObj.push(image);
});
// open the popup
$j.magnificPopup.open({
items: galleryObj,
gallery: {
enabled: true
},
});
});