Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
P
PWATraining
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
training
PWATraining
Commits
acf85360
Commit
acf85360
authored
Jul 27, 2020
by
pwatraining
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
starter
parent
5f17c013
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
17 additions
and
370 deletions
+17
-370
index.html
src/index.html
+0
-1
app.js
src/js/app.js
+15
-293
share.js
src/js/share.js
+1
-20
manifest.json
src/manifest.json
+0
-55
sw.js
src/sw.js
+1
-1
No files found.
src/index.html
View file @
acf85360
...
...
@@ -13,7 +13,6 @@
<title>
PWATraining
</title>
<link
rel=
"shortcut icon"
href=
"/favicon.ico"
>
<link
rel=
"manifest"
href=
"/manifest.json"
>
<link
rel=
"canonical"
href=
"https://uitmpwatraining.web.app/"
>
...
...
src/js/app.js
View file @
acf85360
...
...
@@ -6,9 +6,6 @@
visibleEl
:
null
,
state
:
null
,
publicVapidKey
:
'BAjGFaPYEOqObLkJr0ToM_S2ZDmi0xNZ6EHwtiVwhEUV7Ji9kgGsXrJOVvrlk2UE2oE4s1jTIvAL3r-vkix7rxs'
,
pushAppName
:
document
.
querySelector
(
'.header__title'
).
textContent
,
appName
:
document
.
querySelector
(
'.header__title'
).
innerHTML
,
isLoading
:
true
,
daysOfWeek
:
[
'Sun'
,
'Mon'
,
'Tue'
,
'Wed'
,
'Thu'
,
'Fri'
,
'Sat'
],
...
...
@@ -139,166 +136,26 @@
};
app
.
registerPush
=
async
function
()
{
toast
(
'Subcribed for push notification.'
);
console
.
info
(
'Registering push...'
);
const
subscription
=
await
app
.
registration
.
pushManager
.
subscribe
({
userVisibleOnly
:
true
,
applicationServerKey
:
app
.
urlBase64ToUint8Array
(
app
.
publicVapidKey
)
});
console
.
info
(
'Push registered.'
);
console
.
info
(
'Sending initial push...'
);
await
fetch
(
'https://api.afb.my/webpush'
,
{
method
:
'POST'
,
headers
:
{
'content-type'
:
'application/json'
},
body
:
JSON
.
stringify
({
regtoken
:
app
.
pushAppName
,
clientid
:
subscription
})
})
.
then
(
function
(
response
)
{
if
(
!
response
.
ok
)
{
localStorage
.
setItem
(
"subWebPush"
,
0
);
document
.
querySelector
(
'#toggle'
).
checked
=
false
;
throw
new
Error
(
'Bad status code from server.'
);
}
return
response
.
json
();
})
.
then
(
function
(
responseData
)
{
if
(
!
(
responseData
.
success
))
{
localStorage
.
setItem
(
"subWebPush"
,
0
);
document
.
querySelector
(
'#toggle'
).
checked
=
false
;
throw
new
Error
(
'Bad response from server.'
);
}
else
{
localStorage
.
setItem
(
"subWebPush"
,
1
);
localStorage
.
setItem
(
"subEntry"
,
JSON
.
stringify
(
subscription
));
toast
(
'To be implemented.'
);
}
});
console
.
info
(
'Respond received.'
);
};
app
.
unregisterPush
=
function
()
{
toast
(
'Push notification is cancelled.'
);
app
.
registration
.
pushManager
.
getSubscription
()
.
then
(
function
(
subscription
)
{
if
(
subscription
)
{
console
.
info
(
'Unregister push...'
);
fetch
(
'https://api.afb.my/webpush/removeme'
,
{
method
:
'DELETE'
,
headers
:
{
'content-type'
:
'application/json'
},
body
:
JSON
.
stringify
({
regtoken
:
app
.
pushAppName
,
clientid
:
subscription
})
})
.
then
(
function
(
response
)
{
if
(
!
response
.
ok
)
{
throw
new
Error
(
'Bad status code from server.'
);
}
return
response
.
json
();
})
.
then
(
function
(
responseData
)
{
if
(
!
(
responseData
.
success
))
{
throw
new
Error
(
'Bad response from server.'
);
}
else
{
localStorage
.
setItem
(
"subWebPush"
,
0
);
console
.
info
(
'Unsubscribed from push notification.'
);
}
});
return
subscription
.
unsubscribe
();
}
else
{
localStorage
.
setItem
(
"subWebPush"
,
0
);
toast
(
'To be implemented.'
);
console
.
info
(
'Subscription not found.'
);
}
})
.
catch
(
function
(
error
)
{
throw
new
Error
(
'Error unsubscribing'
,
error
);
});
};
app
.
updateSubscriptionToTheServer
=
async
function
(
subscription
)
{
console
.
info
(
'Updating subscription...'
);
await
fetch
(
'https://api.afb.my/webpush/updateme'
,
{
method
:
'POST'
,
headers
:
{
'content-type'
:
'application/json'
},
body
:
JSON
.
stringify
({
regtoken
:
app
.
pushAppName
,
clientid
:
subscription
})
})
.
then
(
function
(
response
)
{
if
(
!
response
.
ok
)
{
localStorage
.
setItem
(
"subWebPush"
,
0
);
document
.
querySelector
(
'#toggle'
).
checked
=
false
;
throw
new
Error
(
'Bad status code from server.'
);
}
return
response
.
json
();
})
.
then
(
function
(
responseData
)
{
if
(
!
(
responseData
.
success
))
{
localStorage
.
setItem
(
"subWebPush"
,
0
);
document
.
querySelector
(
'#toggle'
).
checked
=
false
;
throw
new
Error
(
'Bad response from server.'
);
}
else
{
localStorage
.
setItem
(
"subWebPush"
,
1
);
localStorage
.
setItem
(
"subEntry"
,
JSON
.
stringify
(
subscription
));
document
.
querySelector
(
'#toggle'
).
checked
=
true
;
}
});
console
.
info
(
'Subscription updated.'
);
};
app
.
askPermission
=
function
()
{
return
new
Promise
(
function
(
resolve
,
reject
)
{
var
permissionResult
=
Notification
.
requestPermission
(
function
(
result
)
{
resolve
(
result
);
});
if
(
permissionResult
)
{
permissionResult
.
then
(
resolve
,
reject
);
}
})
.
then
(
function
(
permissionResult
)
{
if
(
permissionResult
!==
'granted'
)
{
document
.
querySelector
(
'#toggle'
).
checked
=
false
;
throw
new
Error
(
'We weren
\'
t granted permission.'
);
}
else
{
app
.
registerPush
();
}
});
};
app
.
subWebPush
=
function
()
{
//unsubscribe
if
(
Notification
.
permission
===
"granted"
&&
localStorage
.
getItem
(
"subWebPush"
)
==
1
)
{
app
.
unregisterPush
();
}
else
if
(
Notification
.
permission
===
"denied"
)
{
document
.
querySelector
(
'#toggle'
).
checked
=
false
;
toast
(
"Please allow notification in your<br>browser's setting first."
);
console
.
info
(
"Notifications permission has been blocked. Please allow notification in your browser's setting first."
);
}
//requestPermission
else
{
app
.
askPermission
();
}
};
app
.
installPromotion
=
function
(
show
=
true
)
{
...
...
@@ -328,25 +185,7 @@
};
app
.
updateOnlineStatus
=
function
()
{
if
(
navigator
.
onLine
)
{
// handle online status
console
.
info
(
'online'
);
document
.
getElementById
(
'menuPush'
).
classList
.
remove
(
"disabled"
);
document
.
getElementById
(
'toggle'
).
removeAttribute
(
"disabled"
);
document
.
querySelector
(
'.header'
).
style
.
filter
=
'grayscale(0)'
;
document
.
querySelector
(
'.logo'
).
style
.
filter
=
'grayscale(0)'
;
}
else
{
// handle offline status
console
.
info
(
'offline'
);
document
.
getElementById
(
'menuPush'
).
classList
.
add
(
"disabled"
);
document
.
getElementById
(
'toggle'
).
setAttribute
(
"disabled"
,
"disabled"
);
document
.
querySelector
(
'.header'
).
style
.
filter
=
'grayscale(1)'
;
document
.
querySelector
(
'.logo'
).
style
.
filter
=
'grayscale(1)'
;
}
};
app
.
fullscreenMsg
=
function
(
msg
,
title
=
app
.
appName
,
obj
=
false
)
{
...
...
@@ -382,75 +221,6 @@
async
function
run
()
{
app
.
registration
=
await
navigator
.
serviceWorker
.
register
(
'/sw.js'
,
{
scope
:
'/'
})
.
then
(
async
function
(
sw
)
{
console
.
info
(
'ServiceWorker registered: '
,
sw
.
scope
);
var
isUpdate
=
false
;
// If this fires we should check if there's a new Service Worker
// waiting to be activated. If so, ask the user to force refresh.
if
(
sw
.
active
)
isUpdate
=
true
;
sw
.
onupdatefound
=
function
(
event
)
{
// If an update is found the spec says that there is a new Service
// Worker installing, so we should wait for that to complete then
// show a notification to the user.
sw
.
installing
.
onstatechange
=
function
(
event
)
{
if
(
this
.
state
===
'installed'
)
{
console
.
info
(
"Service Worker Installed."
);
if
(
isUpdate
)
{
app
.
fullscreenMsg
(
'New version is available!<br/>We need to reload this web app to update all changes.'
,
app
.
appName
,
{
right
:
{
label
:
'OK'
,
action
:
app
.
reloadWebApp
}}
);
}
else
{
toast
(
app
.
appName
+
' ready for offline use.'
);
}
}
else
{
console
.
info
(
"New Service Worker state:"
,
this
.
state
);
}
};
};
await
sw
.
pushManager
.
getSubscription
().
then
(
function
(
sub
)
{
if
(
sub
===
null
)
{
// Update UI to ask user to register for Push
//console.info('Not subscribed to push service!');
localStorage
.
setItem
(
"subWebPush"
,
0
);
document
.
querySelector
(
'#toggle'
).
checked
=
false
;
}
else
{
// We have a subscription, update the database
//console.info('Subscription object: ', sub);
if
(
localStorage
.
getItem
(
"subWebPush"
)
==
0
)
{
// insert subscription to the server
app
.
updateSubscriptionToTheServer
(
sub
);
}
else
if
(
localStorage
.
getItem
(
"subWebPush"
)
==
1
&&
!
localStorage
.
getItem
(
"subEntry"
))
{
// update changes subscription to the server
app
.
updateSubscriptionToTheServer
(
sub
);
}
else
if
(
localStorage
.
getItem
(
"subWebPush"
)
==
1
&&
localStorage
.
getItem
(
"subEntry"
)
&&
sub
.
endpoint
!==
JSON
.
parse
(
localStorage
.
getItem
(
"subEntry"
)).
endpoint
)
{
console
.
info
(
"New: "
+
sub
.
endpoint
);
console
.
info
(
"Old: "
+
JSON
.
parse
(
localStorage
.
getItem
(
"subEntry"
)).
endpoint
);
console
.
info
(
'Subscription changed!'
);
// update changes subscription to the server
app
.
updateSubscriptionToTheServer
(
sub
);
}
}
});
return
sw
;
})
.
catch
(
function
(
err
)
{
console
.
error
(
'Unable to register service worker.'
,
err
);
});
};
app
.
nextTick
=
function
()
{
...
...
@@ -635,54 +405,6 @@
event
.
stopPropagation
();
});
window
.
addEventListener
(
'online'
,
app
.
updateOnlineStatus
);
window
.
addEventListener
(
'offline'
,
app
.
updateOnlineStatus
);
/************************************************************************
*
* Code required to start the app
*
* NOTE: To simplify this codelab, we've used localStorage.
* localStorage is a synchronous API and has serious performance
* implications. It should not be used in production applications!
* Instead, check out IDB (https://www.npmjs.com/package/idb) or
* SimpleDB (https://gist.github.com/inexorabletash/c8069c042b734519680c)
************************************************************************/
/** custom pwa install prompt **/
var
deferredPrompt
;
window
.
addEventListener
(
'beforeinstallprompt'
,
function
(
e
)
{
// Prevent the mini-infobar from appearing on mobile
e
.
preventDefault
();
// Stash the event so it can be triggered later.
deferredPrompt
=
e
;
// Update UI notify the user they can install the PWA
app
.
installPromotion
(
true
);
});
app
.
buttonInstall
.
addEventListener
(
'click'
,
function
(
e
)
{
// Show the install prompt
deferredPrompt
.
prompt
();
// Wait for the user to respond to the prompt
deferredPrompt
.
userChoice
.
then
(
function
(
choiceResult
)
{
if
(
choiceResult
.
outcome
===
'accepted'
)
{
app
.
reloadWebApp
();
console
.
info
(
'User accepted the install prompt'
);
}
else
{
app
.
pwahomescreen
.
style
.
display
=
'none'
;
console
.
info
(
'User dismissed the install prompt'
);
}
// Hide the app provided install promotion
app
.
installPromotion
(
false
);
});
});
window
.
addEventListener
(
'appinstalled'
,
function
()
{
// Hide the app provided install promotion
app
.
installPromotion
(
false
);
// Log install to analytics
console
.
info
(
'installed to homescreen'
);
});
window
.
addEventListener
(
'load'
,
function
()
{
console
.
group
(
'[Starting App]'
);
...
...
src/js/share.js
View file @
acf85360
(
function
()
{
'use strict'
;
function
webShare
()
{
var
title
=
'Training PWA UiTM'
;
var
text
=
'(WIP-Working In Progress)'
;
var
url
=
document
.
querySelector
(
'link[rel=canonical]'
).
href
;
//console.log(title + "\n" + text + '\n⇒ ' + url);
if
(
navigator
.
share
===
undefined
)
{
//toast('Unsupported feature: Web Share');
//console.log('Error: Unsupported feature: navigator.share');
window
.
open
(
"https://api.whatsapp.com/send?text="
+
window
.
encodeURIComponent
(
text
+
'
\
n⇒ '
+
url
));
return
;
}
navigator
.
share
({
title
:
title
,
text
:
text
,
url
:
url
})
.
then
(
function
()
{})
.
catch
(
function
(
error
)
{});
}
document
.
querySelector
(
'#btnShare'
).
addEventListener
(
'click'
,
webShare
);
})();
src/manifest.json
deleted
100644 → 0
View file @
5f17c013
{
"name"
:
"PWA Training"
,
"short_name"
:
"PWATraining"
,
"description"
:
"Initial release of web app. Work-in-progress (WIP)."
,
"theme_color"
:
"#2f3ba2"
,
"background_color"
:
"#3e4eb8"
,
"display"
:
"standalone"
,
"orientation"
:
"portrait"
,
"scope"
:
"/"
,
"start_url"
:
"/?utm_source=standalone&utm_medium=pwa"
,
"icons"
:
[
{
"src"
:
"images/icons/icon-72x72.png"
,
"sizes"
:
"72x72"
,
"type"
:
"image/png"
},
{
"src"
:
"images/icons/icon-96x96.png"
,
"sizes"
:
"96x96"
,
"type"
:
"image/png"
},
{
"src"
:
"images/icons/icon-128x128.png"
,
"sizes"
:
"128x128"
,
"type"
:
"image/png"
},
{
"src"
:
"images/icons/icon-144x144.png"
,
"sizes"
:
"144x144"
,
"type"
:
"image/png"
},
{
"src"
:
"images/icons/icon-152x152.png"
,
"sizes"
:
"152x152"
,
"type"
:
"image/png"
},
{
"src"
:
"images/icons/icon-192x192.png"
,
"sizes"
:
"192x192"
,
"type"
:
"image/png"
},
{
"src"
:
"images/icons/icon-384x384.png"
,
"sizes"
:
"384x384"
,
"type"
:
"image/png"
},
{
"src"
:
"images/icons/icon-512x512.png"
,
"sizes"
:
"512x512"
,
"type"
:
"image/png"
}
],
"lang"
:
"English"
,
"splash_pages"
:
null
}
src/sw.js
View file @
acf85360
...
...
@@ -3,7 +3,7 @@
if
(
workbox
)
{
console
.
log
(
`Yay! Workbox is loaded 🎉`
);
workbox
.
precaching
.
precacheAndRoute
([{
"revision"
:
"
56dceb8d62294cd2524cf532bdf8eec7"
,
"url"
:
"index.html"
},{
"revision"
:
"6f38b559ee2733468231d0e3589a46f2"
,
"url"
:
"favicon.ico"
},{
"revision"
:
"841ccc0972018aa8e1ff3336f9279847"
,
"url"
:
"css/app.css"
},{
"revision"
:
"64cda5a0c8525157ac311b4c0984a650"
,
"url"
:
"js/app.js"
},{
"revision"
:
"ae75e72cfa193100f2baba436c50616b"
,
"url"
:
"js/menu.js"
},{
"revision"
:
"70b828e6a680aa61b26c26b8ed704b92"
,
"url"
:
"js/share.js"
},{
"revision"
:
"862385e0c7db3e2cd56c62c89388baa7
"
,
"url"
:
"js/swipe.js"
},{
"revision"
:
"609e8f6ce7aa15cd2e5effde31057a80"
,
"url"
:
"js/toast.js"
},{
"revision"
:
"9cff0b914c679f32a3c1e4162f80522a"
,
"url"
:
"images/badges/notification_192.png"
},{
"revision"
:
"784b1c63c7be412d166db4a3d49f2501"
,
"url"
:
"images/icons/icon-128x128.png"
},{
"revision"
:
"adb787791bb14d1a5a076321c886b171"
,
"url"
:
"images/icons/icon-144x144.png"
},{
"revision"
:
"e25a0afa07977ad1039a46b9ab82daee"
,
"url"
:
"images/icons/icon-152x152.png"
},{
"revision"
:
"86e1f0fae80ecb97faad31f57d88aaec"
,
"url"
:
"images/icons/icon-192x192.png"
},{
"revision"
:
"72c220ac025d55ff95abe164ffb31db4"
,
"url"
:
"images/icons/icon-384x384.png"
},{
"revision"
:
"720fb062cb6d0f37070a9d877967a894"
,
"url"
:
"images/icons/icon-512x512.png"
},{
"revision"
:
"c03ad90690383f8dc249bb6c7a407aab"
,
"url"
:
"images/icons/icon-72x72.png"
},{
"revision"
:
"2ee2cc270deb2d95e2c8773398eff1fe"
,
"url"
:
"images/icons/icon-96x96.png"
},{
"revision"
:
"1b9053762212073bbade3145680cbf41"
,
"url"
:
"images/logoUiTM.svg"
}]);
workbox
.
precaching
.
precacheAndRoute
([{
"revision"
:
"
b1c77f9c5225951a9c6bd70d4188fa6a"
,
"url"
:
"index.html"
},{
"revision"
:
"6f38b559ee2733468231d0e3589a46f2"
,
"url"
:
"favicon.ico"
},{
"revision"
:
"fa694d319ff249bbafc9b0ebeb5bdd8a"
,
"url"
:
"css/app.css"
},{
"revision"
:
"0d606a447f16af75e775b64b27f3c442"
,
"url"
:
"js/app.js"
},{
"revision"
:
"ae75e72cfa193100f2baba436c50616b"
,
"url"
:
"js/menu.js"
},{
"revision"
:
"07eab90e6269c3f19ddc34ddfb890adf"
,
"url"
:
"js/share.js"
},{
"revision"
:
"fc8aef5e3399c8fb6efea89b54459f11
"
,
"url"
:
"js/swipe.js"
},{
"revision"
:
"609e8f6ce7aa15cd2e5effde31057a80"
,
"url"
:
"js/toast.js"
},{
"revision"
:
"9cff0b914c679f32a3c1e4162f80522a"
,
"url"
:
"images/badges/notification_192.png"
},{
"revision"
:
"784b1c63c7be412d166db4a3d49f2501"
,
"url"
:
"images/icons/icon-128x128.png"
},{
"revision"
:
"adb787791bb14d1a5a076321c886b171"
,
"url"
:
"images/icons/icon-144x144.png"
},{
"revision"
:
"e25a0afa07977ad1039a46b9ab82daee"
,
"url"
:
"images/icons/icon-152x152.png"
},{
"revision"
:
"86e1f0fae80ecb97faad31f57d88aaec"
,
"url"
:
"images/icons/icon-192x192.png"
},{
"revision"
:
"72c220ac025d55ff95abe164ffb31db4"
,
"url"
:
"images/icons/icon-384x384.png"
},{
"revision"
:
"720fb062cb6d0f37070a9d877967a894"
,
"url"
:
"images/icons/icon-512x512.png"
},{
"revision"
:
"c03ad90690383f8dc249bb6c7a407aab"
,
"url"
:
"images/icons/icon-72x72.png"
},{
"revision"
:
"2ee2cc270deb2d95e2c8773398eff1fe"
,
"url"
:
"images/icons/icon-96x96.png"
},{
"revision"
:
"1b9053762212073bbade3145680cbf41"
,
"url"
:
"images/logoUiTM.svg"
}]);
workbox
.
googleAnalytics
.
initialize
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment