Web Share API - link and text does not appear on social media - javascript

I want to use web share api, so i can share specific image coming from google spreadsheet with text and description, but unfortunatelly only image is being shared to facebook. The text, title and url it's missing. For whatsapp if working fine for example. Can anyone give hand for this? Thanks
Code below:
`
async function share() {
const imageQuote = '<?=$image_quote; ?>';
const response = await fetch(imageQuote);
const blob = await response.blob();
let pageTitle = 'THe Page';
let pageText = document.getElementsByClassName("quote")[0].innerText;
let pageUrl = window.location.href;
const filesArray = [
new File(
[blob],
'panion.jpg',
{
type: blob.type,
lastModified: new Date().getTime()
}
)
];
const shareData = {
title: pageTitle,
text: pageText,
url: pageUrl,
files: filesArray,
};
if (navigator.share) {
navigator
.share(shareData)
.then(() => console.log("Successful share"))
.catch((error) => console.log("Error sharing", error));
} else {
console.error("Browser doesn't support Web Share API");
}
console.log(shareData);
}
function shareThisQuote() {
return share();
}
`

Related

How can I integrate SvelteKit and Google Forms?

SvelteKit's breaking change of Jan 19 (see here for details) means that my Google Forms integration is no longer working.
It was a minor struggle to get it working in the first place, and I can't bring this up to date — I repeatedly get the error message, "To access the request body use the text/json/arrayBuffer/formData methods, e.g. body = await request.json()", and a link to the GitHub conversation.
Here's my Contact component...
<script>
let submitStatus;
const submitForm = async (data) => {
submitStatus = 'submitting';
const formData = new FormData(data.currentTarget);
const res = await fetch('contact.json', {
method: 'POST',
body: formData
});
const { message } = await res.json();
submitStatus = message;
};
const refreshForm = () => {
/* Trigger re-render of component */
submitStatus = undefined;
};
</script>
... and here's the corresponding contact.json.js:
export const post = async (request) => {
const name = request.body.get('name');
const email = request.body.get('email');
const message = request.body.get('message');
const res = await fetch(`URL TO RELEVANT GOOGLE FORM GOES HERE`);
if (res.status === 200) {
return {
status: 200,
body: { message: 'success' }
};
} else {
return {
status: 404,
body: { message: 'failed' }
};
}
};
Any help would be greatly appreciated!
The fix is, in fact, relatively simple, and involved only a tiny change to the existing code. I had to access event.request (destructured to request), and proceed from there, prompted by this answer to a similar question. So, after that, contact.json.js looks like...
export const post = async ({ request }) => {
const body = await request.formData();
const name = body.get('name');
const email = body.get('email');
const message = body.get('message');
const response = await fetch(`URL TO RELEVANT GOOGLE FORM GOES HERE`);
if (response.status === 200) {
return {
status: 200,
body: { message: 'success' }
};
} else {
return {
status: 404,
body: { message: 'failed' }
};
}
};
(Note, too, that this whole form was based upon this video by WebJeda, which won't now work with the latest SvelteKit build, but will with this simple alteration.)

Text -> PNG -> ReadStream, all done on the front-end?

I'm not sure if this is even possible, but here's what I'm trying to do:
Let the user enter some text
Generate a PNG from that text
Upload it to Pinata, which requires it to be in ReadStream format
Do all of this on the front-end
I've managed to accomplish (1) and (2) using html2canvas.
The tricky part is (3). The reason it has to be in ReadStream format is because that's the format Pinata's SDK wants:
const fs = require('fs');
const readableStreamForFile = fs.createReadStream('./yourfile.png');
const options = {
pinataMetadata: {
name: MyCustomName,
keyvalues: {
customKey: 'customValue',
customKey2: 'customValue2'
}
},
pinataOptions: {
cidVersion: 0
}
};
pinata.pinFileToIPFS(readableStreamForFile, options).then((result) => {
//handle results here
console.log(result);
}).catch((err) => {
//handle error here
console.log(err);
});
I realize that this would be no problem to do on the backend with node, but I'd like to do it on the front-end. Is that at all possible? Or am I crazy?
I'm specifically using Vue if that matters.
For anyone interested the solution ended up being using fetch+blob:
const generateImg = async () => {
const canvas = await html2canvas(document.getElementById('hello'));
const img = canvas.toDataURL('image/png');
const res = await fetch(img);
return res.blob();
};
This blob can then be passed into a more manual version of their SDK:
const uploadImg = (blob: Blob) => {
const url = `https://api.pinata.cloud/pinning/pinFileToIPFS`;
const data = new FormData();
data.append('file', blob);
const metadata = JSON.stringify({
name: 'testname',
});
data.append('pinataMetadata', metadata);
const pinataOptions = JSON.stringify({
cidVersion: 0,
});
data.append('pinataOptions', pinataOptions);
return axios
.post(url, data, {
maxBodyLength: 'Infinity' as any, // this is needed to prevent axios from erroring out with large files
headers: {
// #ts-ignore
'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
pinata_api_key: apiKey,
pinata_secret_api_key: apiSecret,
},
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
};

Electron: print iframe given reference to it

I would like to use the react-to-print library to print an iframe from my Electron app. How can I use the iframe reference to get the correct window/element to print?
const handleElectronPrint = async (target: HTMLIFrameElement) {
// Instead of this (printing the whole page)
// let win = BrowserWindow.getFocusedWindow();
// How do I print just the referenced iframe?
// `target` iframe has id="printWindow", how to select it?
let win = BrowserWindow.getMyIframe();
// Is this the right way to do the print once we have the iframe?
const options = { printBackground: true };
win.webContents.print(options, (success, failureReason) => {
if (!success) console.log(failureReason);
console.log('Print Initiated');
});
};
<ReactToPrint
...
print={handleElectronPrint}
/>
You need to convert the iframe object to Data URL. And load the URL in a new hidden BrowserWindow object.
Build data URL in Renderer process and send the URL to Main process using preload. In main process do the BrowserWindow.loadURL and printing.
App.js
// Send print request to the Main process
this.handlePrint = function (target) {
return new Promise(() => {
console.log('forwarding print request to the main process...');
// convert the iframe into data url
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
let data = target.contentWindow.document.documentElement.outerHTML;
//console.log(data);
var blob = new Blob([data], { type: 'text/html' });
var url = URL.createObjectURL(blob);
window.electronAPI.printComponent(url, (response) => {
console.log('Main: ', response);
});
});
};
main.js
// List of all options at -
// https://www.electronjs.org/docs/latest/api/web-contents#contentsprintoptions-callback
const printOptions = {
silent: false,
printBackground: true,
color: true,
margin: {
marginType: 'printableArea',
},
landscape: false,
pagesPerSheet: 1,
collate: false,
copies: 1,
header: 'Page header',
footer: 'Page footer',
};
ipcMain.handle('printComponent', (event, url) => {
let win = new BrowserWindow({ show: false });
win.loadURL(url);
win.webContents.on('did-finish-load', () => {
win.webContents.print(printOptions, (success, failureReason) => {
console.log('Print Initiated in Main...');
if (!success) console.log(failureReason);
});
});
return 'done in main';
});
preload.js
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
printComponent: async (url, callback) => {
let response = await ipcRenderer.invoke('printComponent', url);
callback(response);
},
});
Here is the list of all print options. Some options like page size, margins, orientation can be set in CSS #page rule refer App.css in my demo app.
Here is demo app on GitHub electron-react-to-print-demo.
Print Preview: There is no, Chrome browser style, inbuilt print preview feature due to these reasons. We need to implement our own workaround. Like print to PDF and show pdf in new window:
//handle preview
ipcMain.handle('previewComponent', (event, url) => {
let win = new BrowserWindow({ title: 'Preview', show: false, autoHideMenuBar: true });
win.loadURL(url);
win.webContents.once('did-finish-load', () => {
win.webContents.printToPDF(printOptions).then((data) => {
let buf = Buffer.from(data);
var data = buf.toString('base64');
let url = 'data:application/pdf;base64,' + data;
win.webContents.on('ready-to-show', () => {
win.show();
win.setTitle('Preview');
});
win.webContents.on('closed', () => win = null;);
win.loadURL(url);
})
.catch((error) => {
console.log(error);
});
});
return 'shown preview window';
});
I've added above preview feature in electron-react-to-print-demo.

Draft-Js not showing my image using an image URL

So, I am currently trying to be able to make it possible to paste an image following this [tutorial][1]. The issue I'm having is that I have my code exactly like this tutorial and every time I paste an image it just acts like there was a line break two times with no text. My handlePastedFiles function runs and returns the URL, and then my insertImage runs and passes the link to the insertImage function.
Also, the image url is from a cloud storage and the URL works when viewing in browser.
Here is my handlePastedFiles function:
const handlePastedFiles = (files) => {
console.log('handlePastedFiles is running')
const formData = new FormData();
formData.append('file', files[0])
console.log(files)
fetch(url,
{method: 'POST', body: formData})
.then(res => {
return res.json()
})
.then(data => {
console.log(data)
if (data.message) {
console.log(data.message)
setEditorState(insertImage(data.message)) //created below
} else {
console.log('no file found')
}
}).catch(err => {
console.log(err)
})
}
and here's my insertImages function:
const insertImage = ( url) => {
console.log('!!!!!', url)
const contentState = editorState.getCurrentContent();
const contentStateWithEntity = contentState.createEntity(
'IMAGE',
'IMMUTABLE',
{ src: url },)
const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
const newEditorState = EditorState.set( editorState, { currentContent: contentStateWithEntity });
return AtomicBlockUtils.insertAtomicBlock(newEditorState, entityKey, ' ');
};
Please any help is much appreciated, and let me know if I need more information. Thank you in advance!
[1]: https://daveteu.medium.com/draftjs-insert-paste-images-into-your-content-820159025258

How do I get if a subreddit that the bot is trying to fetch doesn't exist?

I have some code that I got together from the help of this community and I don't know how to get if the bot can't send a random post from a subreddit because it doesn't exist? This is the code:
if (msg.content.startsWith('-reddit ')) {
const subname = msg.content.slice(8);
const mxlenght = 30;
if (subname.length >= mxlenght) {
msg.reply('Ez a subreddit név meghaladja a 30 karakteres maximumot.');
} else {
function loadMemes() {
// Fetch JSON
return (
fetch(
'https://www.reddit.com/r/' + subname + '.json?limit=800&?sort=hot&t=all'
)
.then((res) => res.json())
// Return the actual posts
.then((json) => json.data.children)
);
}
function postRandomMeme(message) {
return loadMemes()
.then((posts) => {
// Get a random post's title and URL
const { title, url } = posts[
Math.floor(Math.random() * posts.length)
].data;
// Create the embed
const embed = new Discord.RichEmbed({
title,
image: { url },
footer: { text: 'Subreddit : r/' + subname },
});
// Send the embed
return message.channel.send(embed);
})
.catch(console.error);
}
// Usage:
postRandomMeme(msg).catch(console.error);
}
}
After some research, I believe the problem is with the URL. First of all, you are fetching data from www.reddit.com, when you should be looking at api.reddit.com. Secondly, there needs to be a slash after the subreddit name.
Here's what the finished URL should look like:
`https://api.reddit.com/r/${subname}/.json?limit=800&?sort=hot&t=all`

Categories

Resources