Skip to content
This repository has been archived by the owner on Jan 5, 2025. It is now read-only.

Commit

Permalink
Applets (#128)
Browse files Browse the repository at this point in the history
  • Loading branch information
black-backdoor authored Jan 2, 2025
1 parent 178ee1d commit 5ee1b0e
Show file tree
Hide file tree
Showing 21 changed files with 331 additions and 482 deletions.
45 changes: 37 additions & 8 deletions docs/components/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
# Components


## Naming Convention

### Classes
- Classes should be named in `PascalCase` (capitalize the first letter of each word).
- The name should be descriptive of the component's functionality, with the prefix `Applet` indicating it's a custom applet component.

### File Name
- The file name should use `kebab-case` (lowercase letters with hyphens between words).
- Use the full name of the component in the file name, starting with `applet-`, followed by the specific functionality (e.g., `network-connection`).
- The file extension should be `.js` (assuming JavaScript).

### Tag Name
- same as the file name, but without the `.js` extension.

### File Location
- Place the file in the `src/components` directory.

### Example
```javascript
class AppletNetworkConnection extends HTMLElement {
// Class code here
}
customElements.define('applet-network-connection', AppletNetworkConnection);
```

File Name: `applet-network-connection.js`


## List
<!-- KEEP ALPHABETICAL ORDER -->

Expand All @@ -11,20 +40,20 @@
* [`<calendar-widget></calendar-widget>` | calendar.js](calendar.md)

- [`<chart-square></chart-square>` | chart-square.js](chart-square.md)
* `<button-power></button-power>` | power.js


### Applets `/components/applet`
* [`<applet-battery></applet-battery>` | battery.js](applet/battery.md)
* [`<applet-battery></applet-battery>` | applet-battery.js](applet-battery.md)
* `<applet-clock></applet-clock>` | clock.js
* `<applet-cpu></applet-cpu>` | cpu.js
* `<applet-cpu></applet-cpu>` | applet-cpu.js
* `<applet-date></applet-date>` | date.js
* [`<applet-network_down></applet-network_down>` | network-down.js](applet/network-down.md)
* [`<applet-network_rtt></applet-network_rtt>` | network-rtt.js](applet/network-rtt.md)
* `<applet-power></applet-power>` | power.js
* `<applet-ram></applet-ram>` | ram.js
* `<applet-sound></applet-sound>` | sound.js
* [`<applet-network-down></applet-network-down>` | applet-network-down.js](applet-network-down.md)
* [`<applet-network-rtt></applet-network-rtt>` | applet-network-rtt.js](applet-network-rtt.md)
* `<applet-ram></applet-ram>` | applet-ram.js
* `<applet-sound></applet-sound>` | applet-sound.js
* `<applet-weather></applet-weather>` | weather.js
* `<applet-wifi></applet-wifi>` | wifi.js
* `<applet-network></applet-network>` | applet-network.js



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

### Script
```html
<script src="/components/applet/battery.js" type="module"></script>
<script src="/components/applet-battery.js" type="module"></script>
```


Expand All @@ -19,4 +19,4 @@
## Properties
* `content` (string)
* `fill`: Slowly fills the battery icon with 10% increments. (Default)
* `percentage`: Displays the battery percentage.
* `percent`: Displays the battery percentage.
20 changes: 20 additions & 0 deletions docs/components/applet-network-down.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# `<applet-network-down>` Component

## Usage
This applet uses the navigation.connection API to get downlink speed and display it as Mbps. If the API is not available, it will display `NaN`.

### Script
```html
<script src="/components/applet-network-down.js" type="module"></script>
```


### Body
```html
<applet-network-down></applet-network-down>
```



## Attributes
* `data-remove-if-unsupported`: If set, the component will remove itself from the DOM if the API is not available.
19 changes: 19 additions & 0 deletions docs/components/applet-network-rtt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# `<applet-network-rtt>` Component

## Usage
This applet uses the navigation.connection API to get the round-trip time and display it as milliseconds. If the API is not available, it will display `NaN`.

### Script
```html
<script src="/components/applet-network-rtt.js" type="module"></script>
```

### Body
```html
<applet-network-rtt></applet-network-rtt>
```



## Attributes
* `data-remove-if-unsupported`: If set, the component will remove itself from the DOM if the API is not available.
21 changes: 0 additions & 21 deletions docs/components/applet/network-down.md

This file was deleted.

19 changes: 0 additions & 19 deletions docs/components/applet/network-rtt.md

This file was deleted.

177 changes: 177 additions & 0 deletions src/components/applet-battery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
class AppletBattery extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });

this.title = 'Battery status: fetching...';
this.text = '?';
this.charging = false;
this.fill = 0;
this.percent = undefined;

this.render();
this.init();
}

connectedCallback() {
this.render();
}

css() {
return `
:host {
display: block;
user-select: none;
aspect-ratio: 1 / 1;
}
svg {
height: 100%;
fill: white;
}
`;
}

template() {
return `
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 2048 2048" style="shape-rendering:geometricPrecision;text-rendering:geometricPrecision;image-rendering:optimizeQuality;fill-rule:evenodd;clip-rule:evenodd">
<style>
${this.text ? '' : '.text { display: none; }'}
${this.charging ? '' : '.charging { display: none; }'}
${this.generateFillClasses()}
</style>
<g>
<!-- BORDER --><path d="M1674.24 770.169V874.24h85.761c17.673 0 32 14.328 32 32v235.52c0 17.674-14.327 32.002-32 32.002h-85.761v104.069c0 36.013-14.71 68.73-38.408 92.43-23.698 23.697-56.417 38.407-92.429 38.407H386.833c-36.012 0-68.73-14.71-92.428-38.408-23.698-23.7-38.408-56.416-38.408-92.43V770.17c0-36.013 14.71-68.73 38.408-92.43 23.698-23.698 56.417-38.408 92.428-38.408h1156.57c36.012 0 68.731 14.71 92.429 38.408 23.697 23.7 38.408 56.417 38.408 92.43zm-64.002 136.071V770.169c0-18.346-7.53-35.05-19.657-47.18-12.127-12.127-28.832-19.656-47.178-19.656H386.833c-18.346 0-35.05 7.53-47.178 19.657-12.127 12.128-19.657 28.833-19.657 47.179v507.662c0 18.346 7.53 35.05 19.657 47.18 12.128 12.127 28.832 19.656 47.178 19.656h1156.57c18.346 0 35.05-7.53 47.178-19.657 12.128-12.129 19.657-28.833 19.657-47.179v-136.07c0-17.673 14.328-32 32.001-32H1728V938.24h-85.76c-17.674 0-32.002-14.328-32.002-32z" />
<!-- TEXT --><text class="text" style="font-family: Arial, sans-serif; font-size: 564.4px; font-weight: 700; text-transform: capitalize; white-space: pre; text-anchor: middle;" x="965.164" y="1218.665">${this.text}</text>
<!-- BOLT --><path class="charging" d="M 2023.852 678.123 L 1924.935 678.123 L 1944.064 563.378 C 1946.46 548.901 1935.33 535.73 1920.64 535.73 L 1798.372 535.73 C 1786.767 535.73 1776.871 544.131 1774.971 555.547 L 1735.41 792.868 C 1732.99 807.344 1744.143 820.516 1758.81 820.516 L 1853.739 820.516 L 1853.739 1010.373 L 2043.833 714.694 C 2053.991 698.889 2042.647 678.123 2023.852 678.123 Z"/>
<path class="fill-1" d="M467.188 773.76c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V773.76z" />
<path class="fill-1" d="M467.188 979.84c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V979.84z" />
<path class="fill-1" d="M467.188 1185.92c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32v-88.321z" />
<path class="fill-2" d="M584.95 773.76c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V773.76z" />
<path class="fill-2" d="M584.95 979.84c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V979.84z" />
<path class="fill-2" d="M584.95 1185.92c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32v-88.321z" />
<path class="fill-3" d="M702.713 773.76c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V773.76z" />
<path class="fill-3" d="M702.713 979.84c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V979.84z" />
<path class="fill-3" d="M702.713 1185.92c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32v-88.321z" />
<path class="fill-4" d="M820.476 773.76c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V773.76z" />
<path class="fill-4" d="M820.476 979.84c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V979.84z" />
<path class="fill-4" d="M820.476 1185.92c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32v-88.321z" />
<path class="fill-5" d="M938.239 773.76c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V773.76z" />
<path class="fill-5" d="M938.239 979.84c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V979.84z" />
<path class="fill-5" d="M938.239 1185.92c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32v-88.321z" />
<path class="fill-6" d="M1056 773.76c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V773.76z" />
<path class="fill-6" d="M1056 979.84c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V979.84z" />
<path class="fill-6" d="M1056 1185.92c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32v-88.321z" />
<path class="fill-7" d="M1173.77 773.76c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V773.76z" />
<path class="fill-7" d="M1173.77 979.84c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V979.84z" />
<path class="fill-7" d="M1173.77 1185.92c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32v-88.321z" />
<path class="fill-8" d="M1291.53 773.76c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V773.76z" />
<path class="fill-8" d="M1291.53 979.84c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V979.84z" />
<path class="fill-8" d="M1291.53 1185.92c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32v-88.321z" />
<path class="fill-9" d="M1409.29 773.76c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V773.76z" />
<path class="fill-9" d="M1409.29 979.84c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V979.84z" />
<path class="fill-9" d="M1409.29 1185.92c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32v-88.321z" />
<path class="fill-10" d="M1527.05 773.76c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V773.76z" />
<path class="fill-10" d="M1527.05 979.84c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32V979.84z" />
<path class="fill-10" d="M1527.05 1185.92c0-17.673-14.328-32-32-32-17.674 0-32.002 14.327-32.002 32v88.32c0 17.673 14.328 32.001 32.001 32.001s32.001-14.328 32.001-32v-88.321z" />
</g>
</svg>
`;
}

generateFillClasses() {
let classes = '';
for (let i = 1; i <= 10; i++) {
if (this.fill < i) {
classes += `.fill-${i} { display: none; }\n`;
}
}
return classes;
}

render() {
this.shadowRoot.innerHTML = `
<style>${this.css()}</style>
${this.template()}
`;
}

updateBatteryStatus(battery) {
const convertSecondsToTime = (seconds) => {
if (seconds === Infinity) return '∞';
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
return `${hours}h ${minutes}m`;
};

const { level, charging } = battery;
const percent = Math.round(level * 100);
let message = `Battery status: ${percent}% `;

if (charging) {
message += battery.chargingTime === Infinity
? 'available (plugged in)'
: `(${convertSecondsToTime(battery.chargingTime)} until full)`;
} else {
message += battery.dischargingTime === Infinity
? 'remaining'
: `(${convertSecondsToTime(battery.dischargingTime)} left)`;
}

this.title = message;
this.charging = charging;
this.percent = percent;

if (this.content === 'percent') {
this.fill = 0;
this.text = this.percent
} else if (this.content === 'fill') {
this.text = '';
this.fill = Math.round(this.percent / 10);
}

this.render();
console.debug(`[setBatteryStatus] battery title updated to: '${message}'`);
}

init() {
if ('getBattery' in navigator) {
navigator.getBattery().then((battery) => {
battery.addEventListener('chargingchange', () => this.updateBatteryStatus(battery));
battery.addEventListener('chargingtimechange', () => this.updateBatteryStatus(battery));
battery.addEventListener('dischargingtimechange', () => this.updateBatteryStatus(battery));
battery.addEventListener('levelchange', () => this.updateBatteryStatus(battery));
this.updateBatteryStatus(battery);
});
} else {
this.title = 'Battery API is not supported';
this.charging = false;
this.fill = 0;
this.text = 'X';
this.render();
}
}

static get observedAttributes() {
return ['content'];
}

attributeChangedCallback(name, oldValue, newValue) {
if (name === 'content' && (newValue !== 'fill' && newValue !== 'percent')) {
console.warn(`BatteryApplet: Invalid attribute for 'content', value: '${newValue}'`);
} else {
console.debug(`BatteryApplet: Attribute 'data-content' changed from '${oldValue}' to '${newValue}'`);
}
this.render();
}

get content() {
const value = this.getAttribute('content');
if (value !== 'fill' && value !== 'percent') {
return 'fill';
}
return value;
}
}

customElements.define('applet-battery', AppletBattery);
15 changes: 4 additions & 11 deletions src/components/applet/cpu.js → src/components/applet-cpu.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class CPUApplet extends HTMLElement {
class AppletCPU extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
Expand Down Expand Up @@ -31,16 +31,9 @@ class CPUApplet extends HTMLElement {
fill: var(--icon-color);
}
p {
margin: 0;
padding: 0;
width: min-content;
height: 100%;
span {
color: var(--text-color);
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
`;
}
Expand All @@ -50,7 +43,7 @@ class CPUApplet extends HTMLElement {
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M5 0a.5.5 0 0 1 .5.5V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2A2.5 2.5 0 0 1 14 4.5h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14a2.5 2.5 0 0 1-2.5 2.5v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14A2.5 2.5 0 0 1 2 11.5H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2A2.5 2.5 0 0 1 4.5 2V.5A.5.5 0 0 1 5 0zm-.5 3A1.5 1.5 0 0 0 3 4.5v7A1.5 1.5 0 0 0 4.5 13h7a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 11.5 3h-7zM5 6.5A1.5 1.5 0 0 1 6.5 5h3A1.5 1.5 0 0 1 11 6.5v3A1.5 1.5 0 0 1 9.5 11h-3A1.5 1.5 0 0 1 5 9.5v-3zM6.5 6a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z"/>
</svg>
<p>${this.percent}%</p>
<span>${this.percent}%</span>
`;
}

Expand All @@ -67,4 +60,4 @@ class CPUApplet extends HTMLElement {
}
}

customElements.define('applet-cpu', CPUApplet);
customElements.define('applet-cpu', AppletCPU);
Loading

0 comments on commit 5ee1b0e

Please sign in to comment.