Browse Source

Merge pull request 'master' (#1) from XimeX/usrspace-browser-addon:master into master

Reviewed-on: https://gitea.usrspace.at/Skystalker/usrspace-browser-addon/pulls/1
master
Stefan 2 months ago
parent
commit
bdf3f62d4c
  1. 12
      .editorconfig
  2. 4
      LICENSE.txt
  3. 4
      README.md
  4. 2
      background/index.html
  5. 140
      background/index.js
  6. 52
      config.js
  7. 23
      icons/favicon.svg
  8. 1
      icons/font-awesome/clock-regular.svg
  9. 1
      icons/font-awesome/cloud-solid.svg
  10. 1
      icons/font-awesome/home-solid.svg
  11. 1
      icons/font-awesome/lock-open-solid.svg
  12. 1
      icons/font-awesome/lock-solid.svg
  13. 1
      icons/font-awesome/wikipedia-w-brands.svg
  14. 94
      icons/gitea-brands.svg
  15. 66
      manifest.json
  16. 26
      package-lock.json
  17. 5
      package.json
  18. BIN
      popup/font/Nunito-Bold.ttf
  19. BIN
      popup/font/Nunito-Italic.ttf
  20. BIN
      popup/font/Nunito-Regular.ttf
  21. 93
      popup/font/OFL.txt
  22. 104
      popup/index.css
  23. 111
      popup/index.html
  24. 163
      popup/index.js

12
.editorconfig

@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*.{html,css,js,json}]
indent_style = tab
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

4
LICENSE.txt

@ -1,6 +1,6 @@
MIT License
Copyright (c) [year] [fullname]
Copyright (c) 2021 /usr/space
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

4
README.md

@ -26,8 +26,8 @@ $ web-ext build -n _usr_space-X.Y.zip
```
## Credits
Used icons from FontAwesome
https://fontawesome.com/license
Used icons from Bootstrap
https://github.com/twbs/icons/blob/main/LICENSE.md
## License
MIT

2
background/index.html

@ -7,4 +7,4 @@
<script type="application/javascript" src="../config.js"></script>
<script type="application/javascript" src="index.js"></script>
</head>
</html>
</html>

140
background/index.js

@ -1,85 +1,87 @@
const fetchJson = (url) => {
return fetch(url).then((response) => (response.json()));
};
function fetchJson(url) {
return fetch(url).then((response) => (response.json()));
}
const fetchCalendar = (days = 28) => {
let url = Config.calenderUrl + '?o=json';
if (days) {
url += '&r=' + days;
}
return fetchJson(url);
};
function fetchCalendar(days = 28) {
let url = `${Config.calenderUrl}?o=json`;
if (days) {
url += `&r=${days}`;
}
return fetchJson(url);
}
const fetchSpaceApi = () => {
return fetchJson(Config.spaceApiUrl);
};
function fetchSpaceApi() {
return fetchJson(Config.spaceApiUrl);
}
const updateBadge = (open) => {
let badgeText, badgeColor;
if (open) {
badgeText = browser.browserAction.setBadgeText({text: 'open'});
badgeColor = browser.browserAction.setBadgeBackgroundColor({color: Config.openColor});
} else {
badgeText = browser.browserAction.setBadgeText({text: ''});
badgeColor = browser.browserAction.setBadgeBackgroundColor({color: null});
}
Promise.all([badgeText, badgeColor])
.then()
.catch((error) => {
console.error(error);
});
};
async function updateBadge(open) {
let badgeText, badgeColor;
if (open) {
badgeText = browser.browserAction.setBadgeText({text: 'open'});
badgeColor = browser.browserAction.setBadgeBackgroundColor({color: Config.openColor});
} else {
badgeText = browser.browserAction.setBadgeText({text: ''});
badgeColor = browser.browserAction.setBadgeBackgroundColor({color: null});
}
try {
await Promise.all([badgeText, badgeColor]);
} catch (error) {
console.error(error);
}
}
const sendNotification = (open) => {
browser.notifications.create('notification-id', {
type: 'basic',
iconUrl: browser.runtime.getURL('icons/logo.svg'),
title: 'Space Status',
message: 'Space ist jetzt ' + (open ? 'offen' : 'geschlossen') + '.'
});
};
function sendNotification(open) {
browser.notifications.create('status-change', {
type: 'basic',
title: 'Space Status',
message: `Space ist jetzt ${open ? 'offen' : 'geschlossen'}.`,
iconUrl: browser.runtime.getURL('icons/favicon.svg')
});
}
const fetchNewData = () => {
fetchCalendar().then((json) => {
window.calendar = json;
}).catch((error) => {
console.error(error);
});
async function fetchNewData() {
try {
const json = await fetchCalendar();
window.calendar = json;
} catch (error) {
console.error(error);
}
fetchSpaceApi().then((json) => {
if (window.spaceApi && window.spaceApi.state.open !== json.state.open) {
sendNotification(json.state.open)
}
window.spaceApi = json;
updateBadge(window.spaceApi.state.open);
}).catch((error) => {
console.error(error);
});
};
try {
const json = await fetchSpaceApi();
if (window.spaceApi && window.spaceApi.state.open !== json.state.open) {
sendNotification(json.state.open)
}
window.spaceApi = json;
updateBadge(window.spaceApi.state.open);
} catch (error) {
console.error(error);
}
}
let intervalHandler = null;
const stopFetching = () => {
if (intervalHandler !== null) {
clearInterval(intervalHandler);
intervalHandler = null;
}
};
const startFetching = () => {
fetchNewData();
if (intervalHandler === null) {
intervalHandler = setInterval(() => {
fetchNewData();
}, Config.refreshTimeout);
}
};
function stopFetching() {
if (intervalHandler !== null) {
clearInterval(intervalHandler);
intervalHandler = null;
}
}
function startFetching() {
fetchNewData();
if (intervalHandler === null) {
intervalHandler = setInterval(() => {
fetchNewData();
}, Config.refreshTimeout);
}
}
window.addEventListener('offline', () => {
stopFetching();
stopFetching();
});
window.addEventListener('online', () => {
startFetching();
startFetching();
});
if (window.navigator.onLine) {
startFetching();
startFetching();
}

52
config.js

@ -1,32 +1,24 @@
window.Config = {
refreshTimeout: 1000 * 60 * 5, // 5min,
spaceApiUrl: 'https://www.usrspace.at/spaceapi.json',
calenderUrl: 'https://www.usrspace.at/calendar.php',
openColor: '#33cc33',
quickLinks: [
{
url: 'https://www.usrspace.at/',
img: 'icons/font-awesome/home-solid.svg',
alt: 'Home',
text: 'Homepage'
},
{
url: 'https://wiki.usrspace.at/',
img: 'icons/font-awesome/wikipedia-w-brands.svg',
alt: 'Wiki',
text: 'Wiki'
},
{
url: 'https://gitea.usrspace.at/',
img: 'icons/gitea-brands.svg',
alt: 'Gitea',
text: 'Gitea'
},
{
url: 'https://cloud.usrspace.at/',
img: 'icons/font-awesome/cloud-solid.svg',
alt: 'Cloud',
text: 'Nextcloud'
}
]
refreshTimeout: 1000 * 60 * 5, // 5min,
spaceApiUrl: 'https://www.usrspace.at/spaceapi.json',
calenderUrl: 'https://www.usrspace.at/calendar.php',
openColor: '#33cc33',
quickLinks: [
{
url: 'https://www.usrspace.at/',
text: 'Homepage'
},
{
url: 'https://wiki.usrspace.at/',
text: 'Wiki'
},
{
url: 'https://gitea.usrspace.at/',
text: 'Gitea'
},
{
url: 'https://cloud.usrspace.at/',
text: 'Nextcloud'
}
]
};

23
icons/favicon.svg

@ -0,0 +1,23 @@
<svg id="root" width="16" height="16" viewBox="-32 -32 64 64" xmlns="http://www.w3.org/2000/svg">
<title>/usr/space</title>
<desc>Logo /usr/space</desc>
<defs>
<style type="text/css">
#root {
stroke: #2AA1BF;
}
@media (prefers-color-scheme: dark) {
#root {
stroke: #FFF;
}
}
</style>
<marker id="circle" viewBox="-4 -4 8 8" markerWidth="8.5" markerHeight="8.5" markerUnits="userSpaceOnUse" refX="3" orient="auto-start-reverse">
<circle cx="0" cy="0" r="2" fill="none" stroke-width="4"/>
</marker>
</defs>
<g fill="none" stroke-width="4">
<path marker-start="url(#circle)" marker-end="url(#circle)" d="M 0,-21.69431 0,-1.299519 a 2.2499999,2.2499999 0 0 0 1.125624,1.948918 l 21.5,12.403846 A 2.25,2.25 0 0 0 26,11.104327 v -24.804808 a 2.2499999,2.2499999 0 0 0 -1.125624,-1.948918 l -23.75,-13.701923 a 2.25,2.25 0 0 0 -2.248752,0 l -23.749999,13.701923 A 2.2499999,2.2499999 0 0 0 -26,-13.700481 v 24.804808 a 2.25,2.25 0 0 0 3.374376,1.948918 L -6.154917,3.550914"/>
<path marker-start="url(#circle)" marker-end="url(#circle)" d="m 18.850376,19.124785 -17.726,10.226537 a 2.25,2.25 0 0 1 -2.248752,0 L -18.844457,19.128198"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

1
icons/font-awesome/clock-regular.svg

@ -1 +0,0 @@
<svg aria-hidden="true" data-prefix="far" data-icon="clock" class="svg-inline--fa fa-clock fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm61.8-104.4l-84.9-61.7c-3.1-2.3-4.9-5.9-4.9-9.7V116c0-6.6 5.4-12 12-12h32c6.6 0 12 5.4 12 12v141.7l66.8 48.6c5.4 3.9 6.5 11.4 2.6 16.8L334.6 349c-3.9 5.3-11.4 6.5-16.8 2.6z"></path></svg>

Before

Width:  |  Height:  |  Size: 536 B

1
icons/font-awesome/cloud-solid.svg

@ -1 +0,0 @@
<svg aria-hidden="true" data-prefix="fas" data-icon="cloud" class="svg-inline--fa fa-cloud fa-w-20" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M537.6 226.6c4.1-10.7 6.4-22.4 6.4-34.6 0-53-43-96-96-96-19.7 0-38.1 6-53.3 16.2C367 64.2 315.3 32 256 32c-88.4 0-160 71.6-160 160 0 2.7.1 5.4.2 8.1C40.2 219.8 0 273.2 0 336c0 79.5 64.5 144 144 144h368c70.7 0 128-57.3 128-128 0-61.9-44-113.6-102.4-125.4z"></path></svg>

Before

Width:  |  Height:  |  Size: 466 B

1
icons/font-awesome/home-solid.svg

@ -1 +0,0 @@
<svg aria-hidden="true" data-prefix="fas" data-icon="home" class="svg-inline--fa fa-home fa-w-18" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M488 312.7V456c0 13.3-10.7 24-24 24H348c-6.6 0-12-5.4-12-12V356c0-6.6-5.4-12-12-12h-72c-6.6 0-12 5.4-12 12v112c0 6.6-5.4 12-12 12H112c-13.3 0-24-10.7-24-24V312.7c0-3.6 1.6-7 4.4-9.3l188-154.8c4.4-3.6 10.8-3.6 15.3 0l188 154.8c2.7 2.3 4.3 5.7 4.3 9.3zm83.6-60.9L488 182.9V44.4c0-6.6-5.4-12-12-12h-56c-6.6 0-12 5.4-12 12V117l-89.5-73.7c-17.7-14.6-43.3-14.6-61 0L4.4 251.8c-5.1 4.2-5.8 11.8-1.6 16.9l25.5 31c4.2 5.1 11.8 5.8 16.9 1.6l235.2-193.7c4.4-3.6 10.8-3.6 15.3 0l235.2 193.7c5.1 4.2 12.7 3.5 16.9-1.6l25.5-31c4.2-5.2 3.4-12.7-1.7-16.9z"></path></svg>

Before

Width:  |  Height:  |  Size: 749 B

1
icons/font-awesome/lock-open-solid.svg

@ -1 +0,0 @@
<svg aria-hidden="true" data-prefix="fas" data-icon="lock-open" class="svg-inline--fa fa-lock-open fa-w-18" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M423.5 0C339.5.3 272 69.5 272 153.5V224H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48h-48v-71.1c0-39.6 31.7-72.5 71.3-72.9 40-.4 72.7 32.1 72.7 72v80c0 13.3 10.7 24 24 24h32c13.3 0 24-10.7 24-24v-80C576 68 507.5-.3 423.5 0z"></path></svg>

Before

Width:  |  Height:  |  Size: 497 B

1
icons/font-awesome/lock-solid.svg

@ -1 +0,0 @@
<svg aria-hidden="true" data-prefix="fas" data-icon="lock" class="svg-inline--fa fa-lock fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M400 224h-24v-72C376 68.2 307.8 0 224 0S72 68.2 72 152v72H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48zm-104 0H152v-72c0-39.7 32.3-72 72-72s72 32.3 72 72v72z"></path></svg>

Before

Width:  |  Height:  |  Size: 422 B

1
icons/font-awesome/wikipedia-w-brands.svg

@ -1 +0,0 @@
<svg aria-hidden="true" data-prefix="fab" data-icon="wikipedia-w" class="svg-inline--fa fa-wikipedia-w fa-w-20" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M640 51.2l-.3 12.2c-28.1.8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3.3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4.2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5.3v13.1c-19.4.6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4.3-3.6 0-10.3.3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5.8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1.2.5z"></path></svg>

Before

Width:  |  Height:  |  Size: 921 B

94
icons/gitea-brands.svg

@ -1,94 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 135.46667 135.46667"
height="512"
width="512">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
style="display:inline"
transform="translate(0,-161.53334)"
id="layer1">
<path
id="path3722"
d="m 27.709937,195.15095 c -9.546573,-0.0272 -22.3392732,6.79805 -21.6317552,23.90397 1.105534,26.72889 25.4565952,29.20839 35.1916502,29.42301 1.068023,5.01357 12.521798,22.30563 21.001818,23.21667 h 37.15277 c 22.27763,-1.66785 38.9607,-75.75671 26.59321,-76.03825 -46.781583,2.47691 -49.995146,2.13838 -88.599758,0 -2.495053,-0.0266 -5.972321,-0.49474 -9.707935,-0.5054 z m 2.491319,9.45886 c 1.351378,13.69267 3.555849,21.70359 8.018216,33.94345 -11.382872,-1.50473 -21.069822,-5.22443 -22.851515,-19.10984 -0.950962,-7.4112 2.390428,-15.16769 14.833299,-14.83361 z"
style="fill:none;fill-opacity:1;stroke:#00000e;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
style="display:inline"
id="layer2">
<rect
ry="5.4825778"
transform="rotate(25.914715)"
y="18.291576"
x="87.508659"
height="34.762054"
width="34.762054"
id="rect4599"
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.24757317;stroke-opacity:1" />
<path
id="path4525"
d="m 79.804947,57.359056 3.241146,1.609954 0,-23.126897 -3.262698,0.01393 z"
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.26644793px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
<g
style="display:inline"
id="layer3">
<g
id="g4539"
style="display:inline">
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
id="path4606"
cx="49.064713"
cy="90.077766"
r="3.4745038"
transform="rotate(-19.796137)" />
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
id="path4606-3"
cx="36.810425"
cy="102.1049"
r="3.4745038"
transform="rotate(-19.796137)" />
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
id="path4606-1"
cx="46.484283"
cy="111.43928"
r="3.4745038"
transform="rotate(-19.796137)" />
<rect
style="fill:#000002;fill-opacity:1;stroke:none;stroke-width:0.27444693;stroke-opacity:1"
id="rect4629-8"
width="2.6726954"
height="27.261492"
x="97.333458"
y="18.061695"
transform="rotate(26.024158)" />
<path
style="fill:none;stroke:#000000;stroke-width:2.68000007;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 76.558096,68.116343 c 12.97589,6.395378 13.012989,4.101862 4.890858,20.907244"
id="path4514" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.6 KiB

66
manifest.json

@ -1,35 +1,35 @@
{
"manifest_version": 2,
"name": "/usr/space",
"version": "0.6",
"description": "An Add-on for the Hacker-/Maker-Space /usr/space.",
"icons": {
"48": "icons/logo.svg",
"96": "icons/logo.svg"
},
"background": {
"page": "background/index.html"
},
"browser_action": {
"browser_style": true,
//"chrome_style": true,
"default_title": "/usr/space",
//"default_icon": "icons/logo.svg",
"default_icon": {
"16": "icons/logo.svg",
"32": "icons/logo.svg"
},
"default_area": "navbar",
"default_popup": "popup/index.html"
},
"permissions": [
"https://www.usrspace.at/*",
"webRequest",
"notifications"
],
"author": "Thomas Rupprecht"
//"developer": {
// "name": "Thomas Rupprecht",
// "url": "https://blog.ximex.at/"
//}
"manifest_version": 2,
"name": "/usr/space",
"version": "0.7",
"description": "An Add-on for the Hacker-/Maker-Space /usr/space.",
"icons": {
"48": "icons/favicon.svg",
"96": "icons/favicon.svg"
},
"background": {
"page": "background/index.html"
},
"browser_action": {
"browser_style": true,
//"chrome_style": true,
"default_title": "/usr/space",
//"default_icon": "icons/favicon.svg",
"default_icon": {
"16": "icons/favicon.svg",
"32": "icons/favicon.svg"
},
"default_area": "navbar",
"default_popup": "popup/index.html"
},
"permissions": [
"https://www.usrspace.at/*",
"webRequest",
"notifications"
],
"author": "Thomas Rupprecht"
//"developer": {
// "name": "Thomas Rupprecht",
// "url": "https://blog.ximex.at/"
//}
}

26
package-lock.json

@ -0,0 +1,26 @@
{
"name": "usrspace-browser-addon",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"devDependencies": {
"web-ext-types": "^3.2.1"
}
},
"node_modules/web-ext-types": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/web-ext-types/-/web-ext-types-3.2.1.tgz",
"integrity": "sha512-oQZYDU3W8X867h8Jmt3129kRVKklz70db40Y6OzoTTuzOJpF/dB2KULJUf0txVPyUUXuyzV8GmT3nVvRHoG+Ew==",
"dev": true
}
},
"dependencies": {
"web-ext-types": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/web-ext-types/-/web-ext-types-3.2.1.tgz",
"integrity": "sha512-oQZYDU3W8X867h8Jmt3129kRVKklz70db40Y6OzoTTuzOJpF/dB2KULJUf0txVPyUUXuyzV8GmT3nVvRHoG+Ew==",
"dev": true
}
}
}

5
package.json

@ -0,0 +1,5 @@
{
"devDependencies": {
"web-ext-types": "^3.2.1"
}
}

BIN
popup/font/Nunito-Bold.ttf

Binary file not shown.

BIN
popup/font/Nunito-Italic.ttf

Binary file not shown.

BIN
popup/font/Nunito-Regular.ttf

Binary file not shown.

93
popup/font/OFL.txt

@ -0,0 +1,93 @@
Copyright 2014 The Nunito Project Authors (https://github.com/googlefonts/nunito)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

104
popup/index.css

@ -1,52 +1,94 @@
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: normal;
src: url('font/Nunito-Regular.ttf') format('truetype');
}
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: bold;
src: url('font/Nunito-Bold.ttf') format('truetype');
}
@font-face {
font-family: 'Nunito Sans';
font-style: italic;
font-weight: normal;
src: url('font/Nunito-Italic.ttf') format('truetype');
}
:root {
--light-blue: #2AA1BF;
--dark-blue: #095C81;
--light-color: #0C0C0C;
--dark-color: #FFFFFF;
--light-background: #F9F9F9;
--dark-background: #4A4A4A;
--light-code-background: #EBEBEB;
--dark-code-background: #383838;
}
body {
width: 360px;
width: 360px;
padding: 6px 12px;
color: var(--light-color);
background-color: var(--light-background);
font-family: 'Nunito Sans';
}
@media (prefers-color-scheme: dark) {
body {
color: var(--dark-color);
background-color: var(--dark-background);
}
}
section.no-padding {
margin: 0 -12px -6px;
}
h2 {
margin: 12px 8px 8px;
margin: 6px 0 4px;
}
summary {
margin: 12px 8px 8px;
margin: 6px 12px 6px;
}
summary > h2 {
margin: 0;
display: inline-block;
margin: 0;
display: inline-block;
}
.panel-list-item > .icon {
text-align: center;
width: 23px;
margin-right: 4px;
time {
font-style: italic;
}
.panel-list-item > .icon > img {
vertical-align: text-bottom;
svg {
vertical-align: text-bottom;
}
#state {
margin: 0 8px;
.panel-section-list {
margin: 0 -12px;
}
#state > img {
vertical-align: text-bottom;
margin-right: 4px;
.panel-list-item > .icon {
text-align: center;
width: 23px;
margin-right: 4px;
}
#calendar {
margin: 0 8px;
}
#calendar > div > img {
vertical-align: text-bottom;
margin-right: 4px;
#calendar > div > svg, #state > svg {
margin-right: 4px;
}
#space-api {
margin: 0;
padding: 0 8px;
height: 240px;
overflow-x: hidden;
overflow-y: scroll;
background-color: #ebebeb;
margin: 0;
padding: 0 8px;
height: 122px;
overflow-x: hidden;
overflow-y: scroll;
background-color: var(--light-code-background);
}
@media (prefers-color-scheme: dark) {
#space-api {
background-color: var(--dark-code-background);
}
}
#space-api code {
font-family: monospace;
font-size: 10px;
font-family: monospace;
font-size: 10px;
}

111
popup/index.html

@ -1,57 +1,70 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>/usr/space</title>
<link rel="stylesheet" href="index.css" />
<meta charset="utf-8">
<title>/usr/space</title>
<link rel="stylesheet" href="index.css" />
</head>
<body>
<!--<header class="panel-section panel-section-header">
<div class="icon-section-header"><img src="../icons/logo.svg" width="32" height="32" alt="/usr/space" /></div>
<div class="text-section-header">/usr/space</div>
</header>-->
<section>
<h2>Aktueller Status</h2>
<div id="state">loading...</div>
</section>
<section>
<h2>Links</h2>
<div class="panel-section panel-section-list">
<div class="panel-list-item link" data-url="https://www.usrspace.at/">
<div class="icon"><img src="../icons/font-awesome/home-solid.svg" width="19" height="19" alt="Home" /></div>
<div class="text">Homepage</div>
<div class="text-shortcut"></div>
</div>
<div class="panel-list-item link" data-url="https://wiki.usrspace.at/">
<div class="icon"><img src="../icons/font-awesome/wikipedia-w-brands.svg" width="19" height="19" alt="Wiki" /></div>
<div class="text">Wiki</div>
<div class="text-shortcut"></div>
</div>
<div class="panel-list-item link" data-url="https://gitea.usrspace.at/">
<div class="icon"><img src="../icons/gitea-brands.svg" width="19" height="19" alt="Gitea" /></div>
<div class="text">Gitea</div>
<div class="text-shortcut"></div>
</div>
<div class="panel-list-item link" data-url="https://cloud.usrspace.at/">
<div class="icon"><img src="../icons/font-awesome/cloud-solid.svg" width="19" height="19" alt="Cloud" /></div>
<div class="text">Nextcloud</div>
<div class="text-shortcut"></div>
</div>
</div>
</section>
<section>
<h2>Nächster Termin</h2>
<div id="calendar">loading...</div>
</section>
<section>
<details>
<summary><h2>SpaceApi JSON</h2></summary>
<pre id="space-api"><code>loading...</code></pre>
</details>
</section>
<section>
<h2>Aktueller Status</h2>
<div id="state">loading...</div>
</section>
<section>
<h2>Links</h2>
<ul class="panel-section panel-section-list">
<li class="panel-list-item link" data-url="https://www.usrspace.at/">
<div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" fill="currentColor" viewBox="0 0 16 16" role="img" aria-label="Homepage">
<path fill-rule="evenodd" d="m8 3.293 6 6V13.5a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 2 13.5V9.293l6-6zm5-.793V6l-2-2V2.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5z"/>
<path fill-rule="evenodd" d="M7.293 1.5a1 1 0 0 1 1.414 0l6.647 6.646a.5.5 0 0 1-.708.708L8 2.207 1.354 8.854a.5.5 0 1 1-.708-.708L7.293 1.5z"/>
</svg>
</div>
<div class="text">Homepage</div>
<div class="text-shortcut"></div>
</li>
<li class="panel-list-item link" data-url="https://wiki.usrspace.at/">
<div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" viewBox="0 0 640 512" fill="currentColor" role="img" aria-level="Wiki">
<path d="M640 51.2l-.3 12.2c-28.1.8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3.3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4.2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5.3v13.1c-19.4.6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4.3-3.6 0-10.3.3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5.8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1.2.5z"/>
</svg>
</div>
<div class="text">Wiki</div>
<div class="text-shortcut"></div>
</li>
<li class="panel-list-item link" data-url="https://gitea.usrspace.at/">
<div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" fill="currentColor" viewBox="0 0 16 16" role="img" aria-label="Gitea">
<path d="M15.698 7.287 8.712.302a1.03 1.03 0 0 0-1.457 0l-1.45 1.45 1.84 1.84a1.223 1.223 0 0 1 1.55 1.56l1.773 1.774a1.224 1.224 0 0 1 1.267 2.025 1.226 1.226 0 0 1-2.002-1.334L8.58 5.963v4.353a1.226 1.226 0 1 1-1.008-.036V5.887a1.226 1.226 0 0 1-.666-1.608L5.093 2.465l-4.79 4.79a1.03 1.03 0 0 0 0 1.457l6.986 6.986a1.03 1.03 0 0 0 1.457 0l6.953-6.953a1.031 1.031 0 0 0 0-1.457"/>
</svg>
</div>
<div class="text">Gitea</div>
<div class="text-shortcut"></div>
</li>
<li class="panel-list-item link" data-url="https://cloud.usrspace.at/">
<div class="icon">
<svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" fill="currentColor" viewBox="0 0 16 16" role="img" aria-label="Nextcloud">
<path d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383z"/>
</svg>
</div>
<div class="text">Nextcloud</div>
<div class="text-shortcut"></div>
</li>
</ul>
</section>
<section>
<h2>Nächster Termin</h2>
<div id="calendar">loading...</div>
</section>
<section class="no-padding">
<details>
<summary><h2>SpaceApi JSON</h2></summary>
<pre id="space-api"><code>loading...</code></pre>
</details>
</section>
<script type="application/javascript" src="../browser-polyfill.js"></script>
<script type="application/javascript" src="../config.js"></script>
<script type="application/javascript" src="index.js"></script>
<script type="application/javascript" src="../browser-polyfill.js"></script>
<script type="application/javascript" src="../config.js"></script>
<script type="application/javascript" src="index.js"></script>
</body>
</html>

163
popup/index.js

@ -1,77 +1,100 @@
Array.from(document.getElementsByClassName('link')).forEach((element) => {
element.addEventListener('click', (event) => {
const newTab = browser.tabs.create({
url: event.currentTarget.dataset.url
});
newTab.then((data) => {
// console.log(data);
}).catch((error) => {
console.error(error);
});
});
});
const calendarSVG = `
<svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" fill="currentColor" viewBox="0 0 16 16" role="img" aria-label="Kalender">
<path d="M11 6.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1z"/>
<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/>
</svg>
`;
const doorClosedSVG = `
<svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" fill="currentColor" viewBox="0 0 16 16" role="img" aria-label="Geschlossen">
<path d="M3 2a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v13h1.5a.5.5 0 0 1 0 1h-13a.5.5 0 0 1 0-1H3V2zm1 13h8V2H4v13z"/>
<path d="M9 9a1 1 0 1 0 2 0 1 1 0 0 0-2 0z"/>
</svg>
`;
const doorOpenSVG = `
<svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" fill="currentColor" viewBox="0 0 16 16" role="img" aria-label="Offen">
<path d="M8.5 10c-.276 0-.5-.448-.5-1s.224-1 .5-1 .5.448.5 1-.224 1-.5 1z"/>
<path d="M10.828.122A.5.5 0 0 1 11 .5V1h.5A1.5 1.5 0 0 1 13 2.5V15h1.5a.5.5 0 0 1 0 1h-13a.5.5 0 0 1 0-1H3V1.5a.5.5 0 0 1 .43-.495l7-1a.5.5 0 0 1 .398.117zM11.5 2H11v13h1V2.5a.5.5 0 0 0-.5-.5zM4 1.934V15h6V1.077l-6 .857z"/>
</svg>
`;
browser.runtime.getBackgroundPage().then((page) => {
updateNextEvent(page.calendar);
updateSpaceApiJson(page.spaceApi);
updateState(page.spaceApi);
}).catch((error) => {
console.error(error);
});
async function linkElementClickListener(event) {
try {
const tab = await browser.tabs.create({url: event.currentTarget.dataset.url});
// console.log(tab);
} catch (error) {
console.error(error);
}
}
const updateNextEvent = (nextEvents) => {
const calendarElement = document.getElementById('calendar');
calendarElement.innerText = '';
async function init() {
const linkElements = Array.from(document.getElementsByClassName('link'));
linkElements.forEach((linkElement) => {
linkElement.addEventListener('click', linkElementClickListener);
});
if (nextEvents.length === 0) {
const hintNode = document.createTextNode('Keine Termine in den nächsten 4 Wochen!');
const strongElement = document.createElement('strong');
strongElement.append(hintNode);
calendarElement.append(strongElement);
return;
}
try {
const page = await browser.runtime.getBackgroundPage();
const nextEventDate = nextEvents[0].begin.substr(0, 10);
const nextEventDateEvents = nextEvents.filter((nextEvent) => (nextEvent.begin.startsWith(nextEventDate)));
updateNextEvent(page.calendar);
updateSpaceApiJson(page.spaceApi);
updateState(page.spaceApi);
} catch (error) {
console.error(error);
}
}
init();
nextEventDateEvents.forEach((nextEventDateEvent) => {
const divElement = document.createElement('div');
divElement.innerHTML = '<img src="../icons/font-awesome/clock-regular.svg" width="19" height="19" alt="Clock" />';
const beginDate = new Date(nextEventDateEvent.begin);
const strongElement = document.createElement('strong');
const timeElement = document.createElement('time');
strongElement.textContent = nextEventDateEvent.name;
timeElement.datetime = beginDate.toISOString();
const dateNode = document.createTextNode(beginDate.toLocaleString());
// divElement.innerText = '';
divElement.append(strongElement);
divElement.append(document.createTextNode(' '));
divElement.append(timeElement);
timeElement.append(dateNode);
if (nextEventDateEvent.location) {
const locationNode = document.createTextNode(' (' + nextEventDateEvent.location + ')');
divElement.append(locationNode);
}
calendarElement.append(divElement);
});
};
function updateNextEvent(nextEvents) {
const calendarElement = document.getElementById('calendar');
calendarElement.innerText = '';
const updateSpaceApiJson = (spaceApi) => {
const spaceApiElement = document.querySelector('#space-api code');
const json = JSON.stringify(spaceApi, null, 2).replace(/ /g, '&nbsp;').replace(/\n/g, '<br/>');
spaceApiElement.innerHTML = json;
// const jsonNode = document.createTextNode(json);
// spaceApiElement.innerText = '';
// spaceApiElement.append(jsonNode);
};
if (nextEvents.length === 0) {
const hintNode = document.createTextNode('Keine Termine in den nächsten 4 Wochen!');
const strongElement = document.createElement('strong');
strongElement.append(hintNode);
calendarElement.append(strongElement);
return;
}
const updateState = (spaceApi) => {
const stateElement = document.getElementById('state');
const since = new Date(spaceApi.state.lastchange * 1000);
const sinceStr = ' seit <time datetime="' + since.toISOString() + '">' + since.toLocaleString() + '</time>';
if (spaceApi.state.open) {
stateElement.innerHTML = '<img src="../icons/font-awesome/lock-open-solid.svg" width="19" height="19" alt="Offen" />Offen' + sinceStr;
} else {
stateElement.innerHTML = '<img src="../icons/font-awesome/lock-solid.svg" width="19" height="19" alt="Geschlossen" />Geschlossen' + sinceStr;
}
};
const nextEventDate = nextEvents[0].begin.substr(0, 10);
const nextEventDateEvents = nextEvents.filter((nextEvent) => (nextEvent.begin.startsWith(nextEventDate)));
nextEventDateEvents.forEach((nextEventDateEvent) => {
const divElement = document.createElement('div');
divElement.innerHTML = calendarSVG;
const beginDate = new Date(nextEventDateEvent.begin);
const strongElement = document.createElement('strong');
const timeElement = document.createElement('time');
strongElement.textContent = nextEventDateEvent.name;
timeElement.datetime = beginDate.toISOString();
const dateNode = document.createTextNode(beginDate.toLocaleString([], {dateStyle: "medium", timeStyle: "short"}));
// divElement.innerText = '';
divElement.append(strongElement, ' ', timeElement);
timeElement.append(dateNode);
if (nextEventDateEvent.location) {
const locationNode = document.createTextNode(` (${nextEventDateEvent.location})`);
divElement.append(locationNode);
}
calendarElement.append(divElement);
});
}
function updateSpaceApiJson(spaceApi) {
const spaceApiElement = document.querySelector('#space-api code');
const json = JSON.stringify(spaceApi, null, 2).replace(/ /g, '&nbsp;').replace(/\n/g, '<br/>');
spaceApiElement.innerHTML = json;
// const jsonNode = document.createTextNode(json);
// spaceApiElement.innerText = '';
// spaceApiElement.append(jsonNode);
}
function updateState(spaceApi) {
const stateElement = document.getElementById('state');
const since = new Date(spaceApi.state.lastchange * 1000);
const sinceStr = ` seit <time datetime="${since.toISOString()}">${since.toLocaleString([], {dateStyle: "medium", timeStyle: "short"})}</time>`;
if (spaceApi.state.open) {
stateElement.innerHTML = `${doorOpenSVG}Offen ${sinceStr}`;
} else {
stateElement.innerHTML = `${doorClosedSVG}Geschlossen ${sinceStr}`;
}
}

Loading…
Cancel
Save