i'm unable to open a link using window.open whithin a http request.
Here is how i tried:
const config = {
headers: {token: this.apiKey, authtoken: token},
};
const url = `https://api.eatsmartapp.de/delivery/users/receipt?id=${this.orderId}`;
// #ts-ignore
this.http.get<any>(url, config).subscribe(dataset => {
window.open('link', '_blank');
}, error => {
});
If i try to open the link outside the subscription area its working fine but if i try to open it in my subscription, nothing is happening on my mobile device
Try using window as a service. In your module.ts file
providers: [
{ provide: Window, useValue: window }
]
Then in your component.ts, or wherever
constructor(private window: Window) {
// ...
}
in which case your window.open would be like
this.http.get<any>(url, config).subscribe(dataset => {
this.window.open(dataset.url, '_blank');
}
Related
So I'm trying to do two things at the same time and it's not going too well.
I have a NextJS app and a Rails API server this app connects to. For authentication I'm using a JWT token stored in an http-only encrypted cookie that the Rails API sets and the front end should not be touching. Naturally that creates a necessity for the frontend to send all the api requests though the NextJs server which proxies them to the real API.
To do that I have set up a next-http-proxy-middleware in my /pages/api/[...path] in the following way:
export const config = { api: { bodyParser: false, externalResolver: true } }
export default function handler(
req: NextApiRequest,
res: NextApiResponse
) {
httpProxyMiddleware(req, res, {
target: process.env.BACKEND_URL,
pathRewrite: [{ patternStr: "^/?api", replaceStr: "" }],
})
}
Which works great and life would be just great, but turns out I need to do the same thing with ActionCable subscriptions. Not to worry, found some handy tutorials, packed #rails/actioncable into my package list and off we go.
import {useCurrentUser} from "../../../data";
import {useEffect, useState} from "react";
const UserSocket = () => {
const { user } = useCurrentUser()
const [roomSocket, setRoomSocket] = useState<any>(null)
const loadConsumer = async () => {
// #ts-ignore
const { createConsumer } = await import("#rails/actioncable")
const newCable = createConsumer('/api/wsp')
console.log('Cable loaded')
setRoomSocket(newCable.subscriptions.create({
channel: 'RoomsChannel'
},{
connected: () => { console.log('Room Connected') },
received: (data: any) => { console.log(data) },
}))
return newCable
}
useEffect(() => {
if (typeof window !== 'undefined' && user?.id) {
console.log('Cable loading')
loadConsumer().then(() => {
console.log('Cable connected')
})
}
return () => { roomSocket?.disconnect() }
}, [typeof window, user?.id])
return <></>
}
export default UserSocket
Now when I go to load the page with that component, I get the log output all the way to Cable connected however I don't see the Room Connected part.
I tried looking at the requests made and for some reason I see 2 requests made to wsp. First is directed at the Rails backend (which means the proxy worked) but it lacks the Cookie headers and thus gets disconnected like this:
{
"type": "disconnect",
"reason": "unauthorized",
"reconnect": false
}
The second request is just shown as ws://localhost:5000/api/wsp (which is my NextJS dev server) with provisional headers and it just hangs up in pending. So neither actually connect properly to the websocket. But if I just replace the /api/wsp parameter with the actual hardcoded API address (ws://localhost:3000/wsp) it all works at once (that however would not work in production since those will be different domains).
Can anyone help me here? I might be missing something dead obvious but can't figure it out.
Using Firebase Dynamic Links in a Managed Workflow Expo app directs to the correct deep link in the app on Android, but on iOS only opens the app in either whatever page was last open or the homepage.
app.config.js
ios: {
associatedDomains: [
'applinks:*.myapp.web.app',
'applinks:myapp.web.app',
'applinks:*.myapp.page.link',
'applinks:myapp.page.link',
],
},
AppNavigation.js
const linking = {
prefixes: [
prefix,
'https://myapp.web.app',
'https://*.myapp.web.app',
],
The apple-app-site-association file stored on myapp.web.app
{
"applinks": {
"apps": [],
"details": [
{
"appID": "1234567890.com.my.app",
"paths": [ "*" ]
}
]
}
}
The Dynamic Link is generated using REST API with the following payload:
const payload = {
dynamicLinkInfo: {
domainUriPrefix: 'https://myapp.page.link',
link: `https://myapp.web.app/${deepLink}`,
androidInfo: {
androidPackageName: com.my.app,
},
iosInfo: {
iosBundleId: com.my.app,
iosAppStoreId: 1234567890,
},
The generated Dynamic Link opens the app and directs to the ${deepLink} on Android as expected, but not on iOS. This was tested in an app built with EAS built.
Ended up solving this myself. Dynamic Links get resolved (converted from short link to full link) automatically on Android, but on iOS this has to be done manually with dynamicLinks().resolveLink(url);
After resolving, the link gets picked up by React Native Navigation and works like a normal deep link.
Full code for Dynamic Links:
const linking = {
prefixes: [
'https://myapp.page.link',
'https://myapp.web.app',
],
async getInitialURL() {
// If the app was opened with a Firebase Dynamic Link
const dynamicLink = await dynamicLinks().getInitialLink();
if (dynamicLink) {
const { url } = dynamicLink;
const resolvedLink = await dynamicLinks().resolveLink(url);
return resolvedLink.url;
}
// If the app was opened with any other link (sometimes the Dynamic Link also ends up here, so it needs to be resolved
const initialUrl = await Linking.getInitialURL();
if (initialUrl) {
const resolvedLink = await dynamicLinks().resolveLink(initialUrl);
return (resolvedLink) ? resolvedLink.url : initialUrl;
}
},
subscribe(listener) {
const handleDynamicLink = (dynamicLink) => {
listener(dynamicLink.url);
};
// Listen to incoming links from deep linking
const unsubscribeToDynamicLinks = dynamicLinks().onLink(handleDynamicLink);
return () => {
// Clean up the event listeners
unsubscribeToDynamicLinks();
};
},
};
In my case I also had to install all 3 of the following libraries:
"#react-native-firebase/analytics": "16.4.3",
"#react-native-firebase/app": "16.4.3",
"#react-native-firebase/dynamic-links": "16.4.3",
My main question is; is there a difference in response time for fetching in localhost vs live/production?
I have a project im building in NextJS, with GraphCMS and I'm using GraphQL/graphql-request to fetch the data. When I first start up localhost and the pages loads, I click a link in the page navigation to go to about page and it literally takes 2 seconds for the data to fetch and the page to change. I'm watching the network tab in Chrome DevTools and the .json file status is (pending) and then switches to 200 once the content is downloaded. Here is a screenshot from DevTools:
When I hover over the waterfall, It says the Waiting for server response is 1.86s and content download is 0.46ms. So is the waiting for server response, something because im on a localhost, or is this something to do with the GraphCMS server were its fetching the data from?
Also you may note that the json file size is only 5.2kB, so its not a large fetch.
To give you a little context on the code, my queries & client are stored in the /lib folder:
// /lib/client.js
import { GraphQLClient } from 'graphql-request'
export const graphcmsClient = () =>
new GraphQLClient(process.env.NEXT_PUBLIC_GRAPHCMS_URL, {
headers: {
authorization: `Bearer ${process.env.GRAPHCMS_TOKEN}`,
},
})
// example of a query in ./lib/queries.js
import { gql } from 'graphql-request'
const blogPageQuery = gql`
fragment BlogPostFields on BlogPost {
id
category
content
coverImage {
id
height
url
width
}
excerpt
published
slug
title
}
`
and here is an example where im using getStaticProps and fetching the query data:
export async function getStaticProps({ params, preview = false }) {
const client = graphcmsClient(preview)
const collectionCards = await getAllCollections()
const { page, navigation } = await client.request(pageQuery, {
slug: params.slug
})
if (!page) {
return {
notFound: true
}
}
const parsedPageData = await parsePageData(page)
return {
props: {
page: parsedPageData,
navigation,
collectionCards,
preview
},
revalidate: 60
}
}
I'm currently using auth0 to authenticate users in a Next.js application.
I'm using the #auth0/nextjs-auth0 SDK and following along with the documentation.
However, I'm having trouble figuring out how to redirect users dynamically after login based on the page they accessed the login form from.
In the app I’m currently trying to build, users can log in from “/” which is the home page, and from the navbar element in “/browse”. However, after logging in, it always redirects back to “/”, while I would like to redirect users to “/browse” or "/browse/[id] if that is where they began the login process from.
I’ve tried using https://community.auth0.com/t/redirecting-to-another-page-other-than-using-nextjs-auth0/66920 as a guide but this method only allows me to redirect to a pre-defined route. I would like to know how I could make the redirect URL dynamic.
Thanks in advance!
Edit: I’ve managed to find a solution for now by digging in to the req object and setting the returnTo value to “referer”.
import { handleAuth, handleLogin } from '#auth0/nextjs-auth0';
const getLoginState = (req, loginOptions) => {
return {
returnTo: req.headers.referer
};
};
export default handleAuth({
async login(req, res) {
try {
await handleLogin(req, res, { getLoginState });
} catch (err) {
res.status(err.status ?? 500).end(err.message)
}
}
});
I’m not seeing any obvious problems so far but I’m not entirely sure if this method has any drawbacks, so I would appreciate any feedback.
How about this?
Step 1: Initialize Auth0 SDK
https://auth0.github.io/nextjs-auth0/modules/instance.html#initauth0
# /lib/auth0,js
import { initAuth0 } from "#auth0/nextjs-auth0";
export default initAuth0({
secret: process.env.SESSION_COOKIE_SECRET,
issuerBaseURL: process.env.NEXT_PUBLIC_AUTH0_DOMAIN,
baseURL: process.env.NEXT_PUBLIC_BASE_URL,
clientID: process.env.NEXT_PUBLIC_AUTH0_CLIENT_ID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
routes: {
callback:
process.env.NEXT_PUBLIC_REDIRECT_URI ||
"http://localhost:3000/api/auth/callback",
postLogoutRedirect:
process.env.NEXT_PUBLIC_POST_LOGOUT_REDIRECT_URI ||
"http://localhost:3000",
},
authorizationParams: {
response_type: "code",
scope: process.env.NEXT_PUBLIC_AUTH0_SCOPE,
},
session: {
absoluteDuration: process.env.SESSION_COOKIE_LIFETIME,
},
});
Step 2: Configure Login
https://auth0.github.io/nextjs-auth0/modules/handlers_login.html#handlelogin
https://auth0.github.io/nextjs-auth0/interfaces/handlers_login.loginoptions.html#returnto
# /pages/api/auth/login.js
import auth0 from "../../../lib/auth0";
export default async function login(req, res) {
let options = {
returnTo: 'http://localhost:3000/dashboard'
}
try {
await auth0.handleLogin(req, res, options);
} catch (error) {
console.error(error);
res.status(error.status || 500).end(error.message);
}
}
Now you will land on the dashboard page after successfully authenticating.
Step 3: Helpful Sanity Check
create /pages/api/auth/callback.js with the following content
import auth0 from "../../../lib/auth0";
const afterCallback = (req, res, session, state) => {
// console.log(session)
console.log(state)
return session
};
export default async function callback(req, res) {
try {
console.log(auth0)
await auth0.handleCallback(req, res, { afterCallback });
} catch (error) {
console.error(error);
res.status(error.status || 500).end(error.message);
}
}
Try logging in and look for the state in the console,
{ returnTo: 'http://localhost:3000/dashboard' }
Cheers!
I am attempting to setup a WordPress Theme as a Progressive Web App. When I run Chromes Audit tool (lighthouse?) I get an uninformative error that I don't know what exactly the problem is. The error is:
Failures: Service worker does not successfully serve the manifest start_url. Unable to fetch start url via service worker
I have hardcoded my start url which is a valid url. Any suggestions on what the issue could be?
https://mywebsite.com/wp-content/themes/mytheme/web.manifest:
...
"scope": "/",
"start_url": "https://mywebsite.com",
"serviceworker": {
"src": "dist/assets/sw/service-worker.js",
"scope": "/aw/",
"update_via_cache": "none"
},
...
}
https://mywebsite.com/wp-content/themes/mytheme/dist/assets/sw/service-worker.js:
...
// The fetch handler serves responses for same-origin resources from a cache.
// If no response is found, it populates the runtime cache with the response
// from the network before returning it to the page.
self.addEventListener('fetch', event => {
// Skip cross-origin requests, like those for Google Analytics.
if (event.request.url.startsWith(self.location.origin)) {
event.respondWith(
caches.match(event.request).then(cachedResponse => {
if (cachedResponse) {
return cachedResponse;
}
return caches.open(RUNTIME).then(cache => {
return fetch(event.request).then(response => {
// Put a copy of the response in the runtime cache.
return cache.put(event.request, response.clone()).then(() => {
return response;
});
});
});
})
);
}
});
I register my SW with the following code and it outputs that it has successfully registered the SW:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register(Vue.prototype.$ASSETS_PATH + 'sw/service-worker.js')
.then(function(registration) {
console.log('Registration successful, scope is:', registration.scope);
})
.catch(function(error) {
console.log('Service worker registration failed, error:', error);
});
}
Please change your start_url to
"start_url": "/"
It has to be a relative url. Please see the documentaion