Rendering native mobile components mixed in with HTML (Capacitor) - reactjs

I'm making a hybrid app with React and Capacitor and I need to render an iOS component (AVPlayerView) mixed in with my HTML. I was wondering if there's any way to create a capacitor plugin (e.g. PlayerPlugin) to handle this. Like:
return (
<div>
<img src="whatever" />
<PlayerPlugin height="300px" width="300px" />
<img src="whatever2" />
</div>
)
Or:
const player = PlayerPlugin({ height: '300px', width: '300px' })
return (
<div>
<img src="whatever" />
{player}
<img src="whatever2" />
</div>
)
And the player would automagically know to place itself between the images.
Alternatively, instead of having it mixed in with HTML, at least making it look like it is, by also passing the position, in addition to the dimensions.
For example:
const player = PlayerPlugin()
const playerRef = useRef(null)
useEffect(() => {
if (!playerRef.current) return
player.height = playerRef.current.offsetHeight
player.width = playerRef.current.offsetWidth
player.top = playerRef.current.offsetLeft
player.left = playerRef.current.offsetTop
player.visible = true
}, [playerRef.current])
return (
<div>
<img src="whatever" />
<div ref="playerRef" style={{ height: '300px', width: '300px' }} />
<img src="whatever2" />
</div>
)
Is it possible to do something like this?

Related

React re-render restarting video

I have a react app with some complex view logic. There is one view where I need to have different parents and conditional renders. This causes my stream ref to be lost, or a video to restart. Is there anyway to set this up so my video instance can reach the new view state without restarting?
I've tried display none but it messes with my view, visibility hidden restarts the video.
here's a sandbox of my problem.
https://codesandbox.io/s/romantic-wood-qnn2x0?file=/src/App.js:0-1004
Here's one solution I thought of.
import { useState } from "react";
import React from "react";
import "./styles.css";
let flex = {
display: "flex"
};
let leftParent = {};
let VidInstance = React.forwardRef((props, ref) => {
return (
<div style={{ display: !props.mute ? "flex" : "none", width: 200 }}>
<video
controls=""
preload="none"
autoPlay
src="https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4"
width="200"
muted={props.mute}
></video>
</div>
);
});
export default function App() {
let [view, setView] = useState(false);
return (
<div className="App">
<flex style={flex}>
<leftParent style={leftParent}>
<Box />
<Box />
<VidInstance key="vid" mute={view} />
</leftParent>
<VidInstance key="vid" mute={!view} />
</flex>
<button onClick={() => setView(!view)}>view</button>
</div>
);
}
let Box = () => {
let boxStyle = {
width: "200px",
margin: "2px",
height: "100px",
background: "blue"
};
return <div style={boxStyle}></div>;
};
Loading both VidInstance at same time to sync their play time.
Wrap VidInstance with a wrapper div and give that div same width as the video to reserve the empty space when your video goes hidden.
Pass mute prop to VidInstance to mute and hide inactive video.
You have to use the tag <source> inside the video tag... its worked for me:
<video width="320" height="240" controls>
<source src="movie.mp4" type="video/mp4">
<source src="movie.ogg" type="video/ogg">
Your browser does not support the video tag.
</video>

How to show couple images in preview of ANTD carousel

I was wondering is it possible to show couple images on single preview of ANTD carousel.
For insrance i have a carousel on which i may have different amount of immages.
The problem is that i want to show all avaliable images in preview without heving to schroll through them.
I tried to change size of immages but that didn't help.
Also i haven't found any properties in ANTD for that.
Does anyone know is it possible?
import { Carousel } from 'antd';
const contentStyle = {
height: '160px',
color: '#fff',
lineHeight: '160px',
textAlign: 'center',
background: '#364d79',
};
ReactDOM.render(
<Carousel effect="fade">
<div>
<h3 style={contentStyle}>1</h3>
</div>
<div>
<h3 style={contentStyle}>2</h3>
</div>
<div>
<h3 style={contentStyle}>3</h3>
</div>
<div>
<h3 style={contentStyle}>4</h3>
</div>
</Carousel>,
mountNode,
);
Here's what seemed to work.
Mainly just added an extra item to my array in 0th position and conditionally rendered a preview frame which included all the images in a grid.
Sample:
const images = [...new Array(5).keys()].map((rowIndex, _, array) => {
if (rowIndex === 0) {
return (
<React.Fragment>
<div key={rowIndex} style={previewStyle}>
{array.map((colIndex) => (
<h3 key={(rowIndex + 1) * (colIndex + 1)} style={h3Style}>
Preview: {colIndex}
</h3>
))}
</div>
</React.Fragment>
);
}
return (
<React.Fragment>
<h3 key={rowIndex} style={{...h3Style, lineHeight: '160px',}}>
{rowIndex}
</h3>
</React.Fragment>
);
});

Images wont show up in Nextjs and Strapi project

Currently I'm using NextJs as my frontend and Strapi as my CMS for my web application. I've added the following data to my Citizenship collection type in Strapi:
This is my code in the NextJs side:
export default function Citizenship({ posts }) {
return (
<>
<div style={{textAlign:"center", marginTop:"20px", fontSize:"25px", color:"#0E2043", fontWeight: "500"}}>CITIZENSHIP</div>
<div class="flexbox-container" style={{margin:"70px", marginTop:"0px"}}>
{
posts &&
posts.map((post) => (
<div style={{ padding: "40px" }}>
<div class="citizen-item" key={post.id}>
<div className="container6">
<img
style={{ height: "50%", width: "100%" }}
src={post.Thumbnail.name}
/>
<div style={{textAlign:"center", color:"#E3AB50", padding:"10px", fontSize:"20px"}}>{post.Title}</div>
<div style={{textAlign:"center", color:"#000", padding:"10px", fontSize:"15px"}}>Access to {post.Countries} countries</div>
<div style={{display:"flex", justifyContent:"center", paddingTop:"20px", paddingBottom:"10px"}}>
<button class="findButton">FIND OUT MORE</button>
</div>
</div>
</div>
</div>
))}
</div>
</>
)
}
export async function getStaticProps() {
const res = await fetch('http://localhost:1337/citizenships');
const posts = await res.json();
return {
props: {posts},
}
}
In my output, everything is coming fine except for the Image where it is only showing my first image and all the others are giving a 404. How do I fix this?
Use console.log(post) and find what your post returns in your browser console . If it gives Thumbnail then use it .Or else use what it gives .
use postman for that route with populate query (at the end add "?populate=*") and u will get the complete position of the url of you image and use it .

Unable to load images dynamically in react app

I have this component :-
const CollectionItem = ({ item }) => (
<div className='collection-item'>
<div
className='image'
style={{
backgroundImage: `url(${item.imageUrl})`
}} />
</div>
</div>
)
my images urls are like ../../assets/images/imageName.jpg
i have tried loading a an image in the css file associated with this component with this exact url. It is working with css, but not in jsx. Please help.
Generally, how you load images in react is to import the image from the specified folder (webpack converts it into the correct source behind the scenes), and then to use that imported variable as the src of the image.
import imgSource from "../../assets/images/imageName.jpg";
const CollectionItem = ({ item }) => (
<div className='collection-item'>
<div
className='image'
style={{
backgroundImage: `url(${imgSource})`
}} />
</div>
</div>
)
EDIT
In the cases where the import depends upon the props, you could simple dynamically import the image within the function itself:
const CollectionItem = ({ item }) => (
import imgSource from `${item.imageUrl}`;
<div className='collection-item'>
<div
className='image'
style={{
backgroundImage: `url(${imgSource})`
}} />
</div>
</div>
)
In the case that it does not work, you can try using require instead
const imgSource = require(item.imageUrl);

React not able to render an array(state) in a single row

The state
state = {
posts: [],
}
The posts gets an API value of
{
"authors": [
{
"authorName": "Sideney Sheldon",
"authorImageURL": "http..."
},
{
"authorName": "Sideney Sheldon",
"authorImageURL": "http..."
},
....
]
}
code
render(){
const postList = posts.length ? (
posts.map(post => {
return (
<div className="" key={this.state.key}>
<div className="containerimager">
<img style={imgb} src={post.authorImageURL} />
</div>
<h6 style={{ marginTop:"23px"}} >{post.authorName}</h6>
</div>
)
})
) :
(
<div className="center">No posts to show</div>
);
return(
{postList}
)
}
The {postlist} returns objects but it returns each object in a new row in the webpage
I want all the results(images) in the same row
can anyone please help?
If you want multiple elements in the same row, you could achieve that with css. Use display: flex(by default flex-direction is row which is what you need) on the wrapper to postList. You can either pass it as a style though JSX or add a class that specifies this property
render(){
const postList = posts.length ? (
posts.map(post => {
return (
<div className="" key={this.state.key}>
<div className="containerimager">
<img style={imgb} src={post.authorImageURL} />
</div>
<h6 style={{ marginTop:"23px"}} >{post.authorName}</h6>
</div>
)
})
) : (
<div className="center">No posts to show</div>
);
return(
<div style={{display: 'flex'}}>{postList}</div>
)
}
Here's a CodeSandbox sample I created using your code.
If you're trying to line up the users horizontally (from left to right), CSS is the way to go. In particular, the <div> that is being mapped has, by default, the display: block style which makes it occupy its own row in the page.
To line up divs side by side, you need to somehow apply the display: inline-block style. In my example I used a style prop, but you will likely want to do it in CSS directly.
This is a CSS problem, you should use display: flex together with flex-direction: row on the parent div which will provide the desired result.
posts.map(post,index => {
return (
<div className="" key={this.state.key}>
<div className="containerimager">
<img style={imgb} src={post.authors[index].authorImageURL} />
</div>
<h6 style={{ marginTop:"23px"}} >{post.authors[index].authorName}</h6>
</div>
)
})
) : (
<div className="center">No posts to show</div>
);
Try this

Resources