How to update a web page in reaction to a push-notification? - javascript

I am exploring the world of push-notifications in Node.js and have one question.
Following a few tutorials, I now have a small app firing a few notifications and those pop up in my web browser as expected.
Here is the question:
Instead of having a notification popping up, would it be possible to have a field in my web page updated?
(For example: a clock or a counter)
If the answer is YES, how can I do it? Do I need to change the service worker? The client? Or what?
Here is the current code:
const SECS = 5 * 1000;
let rankVal = 0, counterVal = 1;
const notificationLoop = setInterval(() => {
let currentDate = new Date(),
timeLag = (currentDate-referDate)/1000
const payload = JSON.stringify({
title:'Event is reached!',
timeLag:timeLag.toString()
});
webPush.sendNotification(subscription,payload).catch(err => console.error(err));
console.log('-- setInterval --' + counterVal + ' : ' + rankVal);
if (counterVal>262144) {clearInterval(notificationLoop);}
rankVal += 1
counterVal *= 2
}, SECS);

Check out pusher, should do exactly what you want:
https://pusher.com
Note, you can use pusher for popups and stuff aswell, but mainly it is really good for keeping track of fields and changing data if someone else is using the site at the same time, etc.

Related

How to schedule a function to run at a certain date?

I have a website that allows users to send themselves a message at a date they choose, but I have no idea how to send it at that specific time. I know there exist CronJobs, but here, I'm not doing anything recurring. It's a one-time event trigger that I need.
I first tried using the native setTimeout like this:
const dueTimestamp = ...;
const timeLeft = dueTimestamp - Date().now();
const timeoutId = setTimeout(() => sendMessage(message), timeLeft);
It works perfectly for short periods, however, I'm not sure if it is reliable for long periods such as years or even decades. Moreover, it doesn't offer much control because if I'd like to modify the dueDate or the message's content, I'd have to stop the Timeout and start a new one.
Is there any package, a library, or a service that allows you to run a NodeJS function at a scheduled time? or do you have any solutions? I've heard of Google Cloud Schedule or Cronhooks, but I'm not sure.
You can use node-schedule library. for example :
you want to run a funcation at 5:30am on December 21, 2022.
const schedule = require('node-schedule');
const date = new Date(2022, 11, 21, 5, 30, 0);
const job = schedule.scheduleJob(date, function(){
console.log('The world is going to end today.');
});
As recommended by user3425506, I simply used a Cron job to fetch the messages from a database and to send the message of those whose timestamps have passed.
Dummy representation:
import { CronJob } from "cron";
import { fakeDB } from "./fakeDB";
const messages = fakeDB.messages;
const job = new CronJob("* * * * * *", () => {
const currentTimestamp = new Date().getTime();
messages.forEach((message, index) => {
if (message.timestamp > currentTimestamp) return;
console.log(message.message);
messages.splice(index, 1);
});
});
job.start();

use handleSeeked() function in videojs

I'm using videojs to play videos on the site and I'm trying to create log on video streams but I have difficulty logging users seeking in videos. I need seek start and end time and it seems that the built in handleSeeked() function in videojs does the job but I can't get it to work. Does anybody know how to use this function?
Update
It seems that this question is about the same problem but the solutions aren't fully working and each one has a little problem.
I was able to get what I wanted with the following code but I had to handle everything on my own so if there's still a better way to do this I'd be happy if you could help me.
var previousTime = 0,
currentTime = 0,
completeTime = 0,
position = 0;
player.on('timeupdate', function () {
previousTime = currentTime;
currentTime = Math.floor(player.currentTime());
// save 'position' so long as time is moving forward with each update
if (previousTime < currentTime) {
position = previousTime;
console.log('pos',position)
previousTime = currentTime;
console.log('pre',previousTime)
}
});
player.on('seeked', function () {
completeTime = Math.floor(player.currentTime());
console.log("User came from: " + position);
console.log("User ended at: " + completeTime);
position= Math.floor(player.currentTime())
});

Getting undefined value in reactJS when substracting

I'm trying to get the interval of time when the user started typing until he submitted his text. When he clicks on the text area the timer starts and gets calculated in seconds (hours * 3600 + minutes * 60 + seconds). Same for the timer to end when he clicks submit.
Now my problem is that when I try to subtract the two values saved in this.state, even if I store them in a var first or if I do a this.setState(), I still get 'undefined'.
overallTime(e){
this.setState({Time: this.state.StartTime - this.state.EndTime})
console.log(this.state.Time)
}
onSubmit = (e) => {
this.overallTime();
var textinput = this.state.inputValue;
var inputLength = textinput.length;
var inputTime = this.state.Time;
if(textinput === this.state.Content)
{
console.log(inputLength)
var lps = inputLength / inputTime;
this.setState({LettersPerSecond: lps})
console.log(lps)
this.setState({message: 'Your score is ' + this.state.LettersPerSecond + ' letters per second! Good job! Refresh the page for another try!'})
}
else
{
this.setState({message: 'Your input is incorrect, refresh the page and start again! Remember, you always learn from your failures, so never give up!'})
}
}
I'd suggest restructuring like this:
overallTime() {
return this.state.EndTime - this.state.StartTime;
}
onSubmit = (e) => {
const totalTime = this.overallTime();
const textinput = this.state.inputValue;
const inputLength = textinput.length;
if (textinput === this.state.Content) {
const lps = inputLength / totalTime;
this.setState({
LettersPerSecond: lps,
message: 'Your score is ' + lps + ' letters per second! Good job! Refresh the page for another try!'
});
} else {
this.setState({
message: 'Your input is incorrect, refresh the page and start again! Remember, you always learn from your failures, so never give up!'
})
}
}
Why?
setState({Time: someValue});
// this.state.Time doesn't have the new value yet at this point
See – State updates may be asynchronous.
There's also a minor logical error – you need to do endTime - startTime, not startTime - endTime.
Your overallTime function is not exactly right – I think you meant something like this:
overallTime() {
this.setState((state) => ({
Time: state.EndTime - state.StartTime
});
}
I strongly recommend reading through the State and Lifecycle section of React docs – it's very well written.
You can use call back function of setState function. you will always get updated state in call back function.
for example:
overallTime(e){
this.setState({Time: this.state.StartTime - this.state.EndTime},
() => console.log(this.state.Time))
}

How to calculate time on a specific screen user spend in react native

I'm trying to calculate time when user open a specific screen,When he enters in the screen the the time starts and when I exit from the screen the time stops and gives the time spend on the screen
here is my code:
componentDidMount = () => {
let date = new Date();
let hours = date.getHours();
let minutes = date.getMinutes();
let seconds = date.getSeconds();
this.setState({
startHour: hours,
startMin: minutes,
startSeconds: seconds,
});
}
Here is ComponentWillunmount
componentWillUnmount() {
let date = new Date();
let endHours = date.getHours();
let endMinutes = date.getMinutes();
let endSeconds = date.getSeconds();
console.log(`${endHours}:${endMinutes}:${endSeconds}`);
console.log(
`${this.state.startHour}:${this.state.startMin}:${this.state.startSeconds}`,
);
}
When he enters in the screen the the time starts and when I exit from
the screen the time stops and gives the time spend on the screen
It's a very important Feature Request by many for web 2.0 applications. So, I write a detailed, working and simple solution on the subject here.
You are requesting a feature already created for this workflow. It's a plugin you can include in any website. It's none other than time-on-site tracking in timeonsite.js
Look at the following code (Use latest version; don't just copy/paste),
<head>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/timeonsite/1.2.0/timeonsitetracker.js"></script>
<script>
var config = {
// track page by seconds. Default tracking is by milliseconds
trackBy: 'seconds',
trackHistoryChange: true, //Single-page React/Angular app
callback: function(data) { /* callback denotes your data tracking is real-time */
console.log(data);
var endPointUrl = 'http://example.com' //Replace with your actual backend API URL http://localhost/tos
if (data && data.trackingType) {
if (data.trackingType == 'tos') {
if (Tos.verifyData(data) != 'valid') {
console.log('Data abolished!');
return;
}
}
// make use of sendBeacon if this API is supported by your browser.
if (navigator && typeof navigator.sendBeacon === 'function') {
data.trasferredWith = 'sendBeacon';
var blob = new Blob([JSON.stringify(data)], {type : 'application/json'});
navigator.sendBeacon(endPointUrl, blob);
}
}
}
};
var Tos;
if (TimeOnSiteTracker) {
Tos = new TimeOnSiteTracker(config);
}
</script>
</head>
Then, when you refresh, reload or navigate the React app page,
You'll see following object directly saved into your table/printed in browser console. Select "persist" in logs,
{
TOSId: 1129620185532,
TOSSessionKey: "14802525481391382263",
TOSUserId: "anonymous",
title: "Test application - Home page",
URL: "http://nature-blogs/pages/home.php"
entryTime: "2021-11-27 13:15:48.663",
currentTime: "2021-11-27 13:17:31.663",
timeOnPage: 103,
timeOnSite: 103,
timeOnPageTrackedBy: "second",
timeOnPageByDuration: "0d 00h 01m 43s",
timeOnSiteByDuration: "0d 00h 01m 43s",
trackingType: "tos",
}
As you can see, the actions
"entryTime" is captured
"exitTime" is captured in seconds/milliseconds depending upon configuration
"type:time_on_site" is captured
"timeOnPage" is captured // individual page time
"timeOnSite" is captured // session overall page time
What else you need? Since it's stored in SQL DB table, you can do analysis/reporting queries yourself. The same is the case for NoSQL as well. Timeonsite.js is supporting both RDBMS and NoSql DB types.
On top of it, 1.Minimize tab, 2.Inactive tab and 3.Switch tab's idle time are all computed and ignored automatically by the tracker itself.
The only thing to note in configuration part is,
trackHistoryChange: true
If the page routing depends on Location Hash or also known as single-page app, include this setting. On the other hand if your web application is a normal page like Wikipedia, avoid setting this line. You are done. For showing the real-time stay time on screen, check this SO post. It's using Jquery to show the results. You can customize it for your React app.
This tracker can be plugged-in in any library not only in React app but also Angular, Jquery, MooTools etc. since it's plain vanilla JS library.
Let me know if you need more input on the subject. I can assist you on this.
I'm not a react dev but this is fairly simple and this would be the approach.
componentDidMount = () => {
/* On init set the start time
Also: multiplying new Date() by 1 will return a timestamp
*/
this.startTime = new Date() * 1;
}
componentWillUnmount() {
/* Then on view destroy set the endTime */
let endTime = new Date() * 1;
/* Subtract the end time with start time, since endTime has greater value. The result
is the difference between start and end time in milliseconds.
*/
let elapsed = endTime - this.startTime;
/* The result is in milliseconds so:
elapsed / 1000 -> is seconds
elapsed / 1000 / 60 -> is minutes
etc.
*/
);
I agree with #masterpreenz
componentDidMount = () => {
this.startTime = new Date() * 1;
}
componentWillUnmount() {
let endTime = new Date() * 1;
let elapsed = endTime - this.startTime;
$('viewPageStayTime').html('You spent '+elaspsed+ ' duration.');
);

How to restart web workers when computer restarts from sleep mode?

I have a simple webworker which keeps the current time of timezone using setInterval
setInterval(() => {
userTimezoneTimestamp = userTimezoneTimestamp + 1000
postMessage(userTimezoneTimestamp);
}, 1000);
It works fine until I put my machine on sleep mode. When I restart the machine from sleep mode, the time which I get from this worker is older.
How can I restart my web worker only when the machine starts up from sleep mode?
There doesn't seem to be any DOM event letting us know about that event.
On my notebook Chrome does fire a non-standard orientationabsolutechange event, but I think not all notebooks have orientation aware hardware and already just Firefox on the same machine doesn't fire it.
But for what you want (an always up to date offset from an API served timestamp), you don't need a WebWorker at all, nor any timer, the computer comes with a good one and not only will it still be up to date after computer sleep, it will even be more precise than your interval which can suffer from time-drift.
All you need is to store the offset you got from your API and the computer's time you received it. Then you just need to get the difference between now and that time of reception and you can easily get your updated offset.
OP noted that they are afraid their users modify their computer's time to an earlier date, thus messing up with Date's values while the page is running. This can be detected. All it takes is to store the last value, and check if the difference with the current one is negative.
( async () => {
const offset_from_API = await getOffsetFromAPI();
const time_received = Date.now();
let last_time = time_received;
const getUpToDateOffset = () => {
const now = Date.now();
// Anti-Back-Time-Travelling check
// (it's a good idea to poll this method quite often too update `last_time`)
if( now - last_time < 0 ) {
throw new Error( 'cheater detected' );
}
last_time = now;
return offset_from_API + (now - time_received);
};
// to compare we will also use an incrementer
let incremented = offset_from_API;
setInterval( () => {
incremented += 1000;
console.clear();
console.log( 'incremented', incremented.toLocaleString( 'en-US' ) );
console.log( 'difference ', getUpToDateOffset().toLocaleString( 'en-US' ) );
}, 1000 );
} )();
function getOffsetFromAPI() { return 1234567; }
setInterval(() => {
/*handle userTimezoneTimestamp stuff every N miliseconds */
}, N);
setInterval(() => {
userTimezoneTimestamp = userTimezoneTimestamp + 1000
postMessage(userTimezoneTimestamp);
}, 1000);

Categories

Resources