How to download image from PWA in Safari iOS13+ - mobile

I am trying to implement downloading images from PWA. I am using
<a target="_blank"
rel="noopener noreferrer"
href="photo.url"
download>Download image</a>
to achieve that. I am good on desktop Chrome and Safari and Chrome for Android. But when I am in a standalone mode (PWA) on Safari iOS 13 I can't close the opened window that was opened to save the file. On iOS 12 there was a button 'Done' and preview of the image.
I have tried solutions from here. But without success; Safari blocks the window.open().

I also encountered the problem. I have a PWA in which images are shown and below the image there is a download button. When having simply assigned the image URL directly to the href of the download button, iOS (latest as of September 2021) did not show any "done" button or the reload icon.
What worked for me is below:
fetch('https://somedomain.tld/somefile.jpg')
.then(function(response) {
if (response.status !== 200) {
alert('An error has occured (' + this.status + ')!');
} else {
response.blob().then(function(blob) {
var objectURL = window.URL.createObjectURL(blob);
document.getElementById('yourimageid').src = objectURL;
document.getElementById('yourdownloadlinkid').href = objectURL;
});
}
});

Related

How to load video from local file URL without MediaStream

What's the way play local videos? This option doesn't work:
const url = '/localVideo.mp4';
<ReactPlayer url={url} width="100%"
height="100%"
controls={true} />
I get the error that src attribute is empty:
MediaError {code: 4, message: 'MEDIA_ELEMENT_ERROR: Empty src
attribute'}
The url is a correct sting, works fine with native <video element.
I checked the sources for the library, and it seems like the MediaStream is required:
if (isMediaStream(url)) {
try {
this.player.srcObject = url
} catch (e) {
this.player.src = window.URL.createObjectURL(url)
}
MDN says it's no longer required. It should work with a string.:
In older versions of the Media Source specification, attaching a
stream to a element required creating an object URL for the
MediaStream. This is no longer necessary, and browsers are removing
support for doing this.

React Quill link sanitization not working in Next.js

I am using the react-quill editor in the next.js app. I am facing issues with adding hyperlinks to text. If I add hyperlinks for ex. www.google.com redirects me to http://localhost:3000/app_name/www.google.com. If I add the hyperlink https://www.google.com it works fine. But the user won't always add HTTP or HTTPS while adding hyperlinks to text. After searching on the internet I found that this issue is related to link sanitization so I added the following code in my next.js app.
import Quill from 'quill'
try {
const Link = Quill.import('formats/link');
Link.sanitize = function (url) {
// quill by default creates relative links if scheme is missing.
if (!url.startsWith('http://') && !url.startsWith('https://')) {
return `http://${url}`
}
return url;
}
} catch (e) {
console.log(e);
}
But the above code is not working well. It works sometimes but also It gives me Server Error ReferenceError: document is not defined error on page refresh.
I have also tried to import Quill as mentioned in the following code:
const { Quill } = dynamic(import("quill"), {
ssr: false,
loading: () => <p>Loading ...</p>,
});
But I am getting TypeError: Quill is undefined

None of the browsers support recording of a video

I have implemented react-webcam and react-video-recorder to take pictures and video respectively using the device's webcam. I have followed the document and both of them work perfectly on my localhost. The issue is when I deploy them, the browser doesn't support recording the video. I have tested it on Chrome, Firefox and Opera, and none of them support it.
I've followed https://www.npmjs.com/package/react-webcam for taking image and https://www.npmjs.com/package/react-video-recorder for recording video through the device's webcam.
class VideoPost extends Component {
handleRecordingComplete = (videoBlob, startedAt, thumbnailBlob, duration) => {
const urlCreator = window.URL || window.webkitURL;
const videoUrl = urlCreator.createObjectURL(videoBlob);
this.setState({ videoSrc: videoUrl, video: videoBlob });
};
onVideoDisplay = () => (
<video
src={this.state.videoSrc}
controls
style={{
height: '200px',
width: '200px'
}}
/>
);
render(){
return(
<div>
<VideoRecorder
onRecordingComplete={this.handleRecordingComplete}
renderLoadingView={this.onVideoDisplay}
/>
</div>
)
}
}
i expect the video to work
however on the live site,
Am i missing out something?
This might be due to insecure origin. Make sure you have deployed your application on https i.e. you have a valid SSL cert applied
Refer - react-webcam's npm page
Note: Browsers will throw an error if the page is loaded from insecure origin. I.e. Use https.

How to make the dev tools not show up on screen by default in Electron?

I am using electron-react-boilerplate to create an Electron-React app. The dev tools show up on the screen by default. How can I make the dev tools only appear when I ask for them and not show up on launch?
Also, there are no errors shown in the console, so the dev tools are not showing up because there's an error.
Just comment or remove this line of code in main.js file (setting devTools to false) this.mainWindow.openDevTools();
(or)
Add the following code to
mainWindow = new BrowserWindow({
width: 1024,
height: 768,
webPreferences: {
devTools: false
}
});
(or)
change the package.json build to npm run build && build --win --x64
(or)
again install npm
If we add devTools: false in webPreferences, DevTools will not show when you start the Electron app. However, it can still be opened by pressing Ctrl + Shift + I.
webPreferences: {
devTools: false
}
Have a look at Slack. It is made with Electron and DevTools does not open when you press Ctrl + Shift + I.
I've had a look at Electron's official documentation, and I found a solution which doesn't allow DevTool's to open when you press Ctrl + Shift + I.
const { app, globalShortcut } = require('electron');
app.on('ready', () => {
// Register a shortcut listener for Ctrl + Shift + I
globalShortcut.register('Control+Shift+I', () => {
// When the user presses Ctrl + Shift + I, this function will get called
// You can modify this function to do other things, but if you just want
// to disable the shortcut, you can just return false
return false;
});
});
But, this will block all other browser's Ctrl + Shift +I
So, you can write the above code whenever your electron app is focused. And, remove it when your app is blur. This way you get a proper solution for this issue.
What makes the Developer Tools appear when the app starts is the line require('electron-debug')() in src/main/main.ts. This function has a showDevTools option which defaults to true, so you should change it to false:
require('electron-debug')({ showDevTools: false });
You will still be able to show the Developer Tools with the shortcut Ctrl + Shift + I or pressing F12, if you want to disable it completely, set webPreferences.devTools to false on new BrowserWindow:
mainWindow = new BrowserWindow({
// ... other settings
webPreferences: {
// ...
devTools: false,
},
});
Just add there these two bold line of code. You will not see devTool after packaging.
const electron = require('electron')
// Module to control application life.
const app = electron.app
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow
var debug = false
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 800, height: 600})
// and load the index.html of the app.
mainWindow.loadURL(`file://${__dirname}/index.html`)
// Open the DevTools.
if(debug) mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
Every answer mentions that the keyboard shortcut CTRL + SHIFT + I still works even after disabling devtools using devTools: false.
This is because of the registered accelerator in the Electron BrowserWindow's default menu. All you have to do is remove the menu using mainWindow.removeMenu() and none of the development related shortcut keys will work again. Even the ones like CTRL + R which reloads the page.
Just want to add that, if you want to disable devTools only when in production mode, you can do:
new BrowserWindow({
webPreferences: {
devTools: !app.isPackaged,
},
})
P.S. This also prevents using shortcuts like Ctrl+Shift+I to toggle the devTools.
Just remove the line
mainWindow.webContents.openDevTools(false);
YEAR 2022
Code that loaded the devtools is in src/main/main.ts
Search this following code:
const isDebug =
process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true';
if (isDebug) {
require('electron-debug')();
}
you need to disable electron debug by comment it
//require('electron-debug')();

Refused to display in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'

I am developing a website that is supposed to be responsive so that people can access it from their phones. The site has got some secured parts that can be logged into using Google, Facebook, ...etc (OAuth).
The server backend is developed using ASP.Net Web API 2 and the front end is mainly AngularJS with some Razor.
For the authentication part, everything is working fine in all browsers including Android but the Google authentication is not working on iPhone and it gives me this error message
Refused to display 'https://accounts.google.com/o/openid2/auth
?openid.ns=http://specs.openid.ne…tp://axschema.org/namePerson
/last&openid.ax.required=email,name,first,last'
in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'.
Now as far I am concerned I do not use any iframe in my HTML files.
I googled around, but no answer got me to fix the issue.
I found a better solution, maybe it can help somebody
replace "watch?v=" by "v/" and it will work
var url = url.replace("watch?v=", "v/");
O.K. after spending more time on this with the help of this SO post
Overcoming "Display forbidden by X-Frame-Options"
I managed to solve the issue by adding &output=embed to the end of the url before posting to the google URL:
var url = data.url + "&output=embed";
window.location.replace(url);
They have set the header to SAMEORIGIN in this case, which means that they have disallowed loading of the resource in an iframe outside of their domain. So this iframe is not able to display cross domain
For this purpose you need to match the location in your apache or any other service you are using
If you are using apache then in httpd.conf file.
<LocationMatch "/your_relative_path">
ProxyPass absolute_path_of_your_application/your_relative_path
ProxyPassReverse absolute_path_of_your_application/your_relative_path
</LocationMatch>
Try to use
https://www.youtube.com/embed/YOUR_VIDEO_CODE
You can find all embeded code in 'Embeded Code' section and that looks like this
<iframe width="560" height="315" src="https://www.youtube.com/embed/YOUR_VIDEO_CODE" frameborder="0" allowfullscreen></iframe>
If you are using iframe for vimeo, change the url from:
https://vimeo.com/63534746
to:
http://player.vimeo.com/video/63534746
It works for me.
For embeding youtube video into your angularjs page, you can simply use following filter for your video
app.filter('scrurl', function($sce) {
return function(text) {
text = text.replace("watch?v=", "embed/");
return $sce.trustAsResourceUrl(text);
};
});
<iframe class="ytplayer" type="text/html" width="100%" height="360" src="{{youtube_url | scrurl}}" frameborder="0"></iframe>
I did the below changes and works fine for me.
Just add the attribute <iframe src="URL" target="_parent" />
_parent: this would open embedded page in same window.
_blank: In different tab
For me the fix was to go into console.developer.google.com and add the application domain to "Javascript Origins" section of OAuth 2 credentials.
I was having the same issue implementing in Angular 9. These are the two steps I did:
Change your YouTube URL from https://youtube.com/your_code to https://youtube.com/embed/your_code.
And then pass the URL through DomSanitizer of Angular.
import { Component, OnInit } from "#angular/core";
import { DomSanitizer } from '#angular/platform-browser';
#Component({
selector: "app-help",
templateUrl: "./help.component.html",
styleUrls: ["./help.component.scss"],
})
export class HelpComponent implements OnInit {
youtubeVideoLink: any = 'https://youtube.com/embed/your_code'
constructor(public sanitizer: DomSanitizer) {
this.sanitizer = sanitizer;
}
ngOnInit(): void {}
getLink(){
return this.sanitizer.bypassSecurityTrustResourceUrl(this.youtubeVideoLink);
}
}
<iframe width="420" height="315" [src]="getLink()" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
If you are using iframe for Google Docs Viewer, change iframe from:
iframe src="https://docs.google.com/viewer?url=' + url_your_document
to:
iframe src="https://docs.google.com/viewer?url=' + url_your_document + '&embedded=true"
It works for me.
Little late, but this error can also be caused if you use a native application Client ID instead of a web application Client ID.
There is a solution that worked for me, referring to the parent. After getting the url that will redirect to google authentication page, you can try the following code:
var loc = redirect_location;
window.parent.location.replace(loc);
Thanks for the question.
For YouTube iframe the first issue is the URL you have given, is it embedded URL or URL link from address bar.
this error for non embed URL but if you want to give non embed URL then you need to code in "safe Pipe" like(for both non embedded or embed URL ) :
import {Pipe, PipeTransform} from '#angular/core';
import {DomSanitizer} from '#angular/platform-browser';
#Pipe({name: 'safe'})
export class SafePipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) {
}
transform(value: any, url: any): any {
if (value && !url) {
const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
let match = value.match(regExp);
if (match && match[2].length == 11) {
console.log(match[2]);
let sepratedID = match[2];
let embedUrl = '//www.youtube.com/embed/' + sepratedID;
return this.sanitizer.bypassSecurityTrustResourceUrl(embedUrl);
}
}
}
}
it will split out "vedioId". You have to get video id then set to URL as embedded.
In Html
<div>
<iframe width="100%" height="300" [src]="video.url | safe"></iframe>
</div>
Angular 2/5
thanks again.
add the below with URL Suffix
/override-http-headers-default-settings-x-frame-options
Had an similar issue embeding youtube chat and I figure it out. Maybe there is a similar solution for similar problem.
Refused to display 'https://www.youtube.com/live_chat?v=yDc9BonIXXI&embed_domain=your.domain.web' in a frame because it set 'X-Frame-Options' to 'sameorigin'
My webpage works with www and without it. So to make it work you need to make sure you load the one that is listed on the embed_domain= value... Maybe there is a variable your missing to tell where to embed your iframe. To fix my problem had to write a script to detect the right webpage and execute proper iframe embed domain name.
<iframe src='https://www.youtube.com/live_chat?v=yDc9BonIXXI&embed_domain=your.domain.web' width="100%" height="600" frameborder='no' scrolling='no'></iframe>
or
<iframe src='https://www.youtube.com/live_chat?v=yDc9BonIXXI&embed_domain=www.your.domain.web' width="100%" height="600" frameborder='no' scrolling='no'></iframe>
Understand you are not using iframes, but still there may be some variable you need to add to your syntax to tell it where the script is going to be used.
On apache you need to edit security.conf:
nano /etc/apache2/conf-enabled/security.conf
and set:
Header set X-Frame-Options: "sameorigin"
Then enable mod_headers:
cd /etc/apache2/mods-enabled
ln -s ../mods-available/headers.load headers.load
And restart Apache:
service apache2 restart
And voila!
Here is code which I used and displayed successfully in Iframe and I am making this code in cshtml in C#.
#if (item.DisplayValue2 != null)
{
<div id="collapse_#item.ID" class="collapse" role="tabpanel" aria-labelledby="heading_#item.ID" data-parent="#accordion" style="">
<div class="card-body">
#item.DisplayValue1
</div>
<br /> <br />
#{
var url = item.DisplayValue2.Replace("watch?v=", "embed/");
}
<iframe width="560" height="315" src=#url frameborder="0" allowfullscreen style="margin-bottom: 25px; margin-left: 25px;">
</iframe></div>
I test all items but this code help me:
?rs:embed=true
For example I want to load a pbix in my application. I use this code :
<iframe id="pageIFrame" class="iFrame" src="http://MyServer/ReportS/powerbi/Test?rs:embed=true"></iframe>
And it works.
Ran into this similar issue while using iframe to logout of sub sites with different domains. The solution I used was to load the iframe first, then update the source after the frame is loaded.
var frame = document.createElement('iframe');
frame.style.display = 'none';
frame.setAttribute('src', 'about:blank');
document.body.appendChild(frame);
frame.addEventListener('load', () => {
frame.setAttribute('src', url);
});
youtube/embed, two flavors:
https://www.youtube.com/embed/watch?v=eAxV4uO8oTU&list=RDeAxV4uO8oTU&start_radio=1
https://www.youtube.com/embed/CNG7yrHHJ5A
paste in your browser and see
the original:
https://www.youtube.com/watch?v=eAxV4uO8oTU&list=RDeAxV4uO8oTU&start_radio=1
https://www.youtube.com/watch?v=CNG7yrHHJ5A
one needs to keep "watch?V=", the other not
in the php file (index.php) add this line in the top
<?php
header('Cross-Origin-Embedder-Policy: require-corp | same-site | same-origin | cross-origin');
?>
if still not work try this
<?php
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Headers: Accept, X-Access-Token, X-Application-Name, X-Request-Sent-Time");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Origin: *");
header('Cross-Origin-Opener-Policy: same-origin');
header('Cross-Origin-Resource-Policy: same-site | same-origin | cross-origin');
header('Cross-Origin-Embedder-Policy: require-corp | same-site | same-origin | cross-origin');
?>

Resources