Create settings dialog and improve AppDialog

Update AppDialog to be able to handle invalid forms, and implement the
settings dialog that communicates via appState
This commit is contained in:
Abász 2023-03-22 13:34:27 +01:00
parent 6aa5c696c6
commit 00d9c824d0
4 changed files with 259 additions and 6 deletions

View File

@ -46,10 +46,15 @@ export class AppDialog extends AppElement {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
button:hover { button:hover:not(.disabled) {
filter: brightness(150%); filter: brightness(150%);
} }
button.disabled {
filter: brightness(50%);
pointer: none
}
fieldset { fieldset {
border: 0; border: 0;
margin: unset; margin: unset;
@ -67,6 +72,8 @@ export class AppDialog extends AppElement {
padding: 0; padding: 0;
} }
` `
@property({ type: Boolean })
isValid = true
@property({ type: Boolean, reflect: true }) @property({ type: Boolean, reflect: true })
dialogOpen dialogOpen
@ -74,13 +81,13 @@ export class AppDialog extends AppElement {
render () { render () {
return html` return html`
<dialog ${ref(this.dialog)} @close=${this.close}> <dialog ${ref(this.dialog)} @close=${this.close}>
<form method="dialog"> <form >
<fieldset role="document"> <fieldset role="document">
<slot></slot> <slot></slot>
</fieldset> </fieldset>
<menu> <menu>
<button value="cancel">Cancel</button> <button formmethod="dialog" value="cancel">Cancel</button>
<button value="confirm">OK</button> <button @click=${this.confirm} type="button" class="${this.isValid ? '' : 'disabled'}" value="confirm">OK</button>
</menu> </menu>
</form> </form>
</dialog> </dialog>
@ -95,6 +102,13 @@ export class AppDialog extends AppElement {
} }
} }
confirm () {
if (this.isValid) {
this.close({ target: { returnValue: 'confirm' } })
this.dialogOpen = false
}
}
firstUpdated () { firstUpdated () {
this.dialog.value.showModal() this.dialog.value.showModal()
} }

View File

@ -7,12 +7,13 @@
import { AppElement, html, css } from './AppElement.js' import { AppElement, html, css } from './AppElement.js'
import { APP_STATE } from '../store/appState.js' import { APP_STATE } from '../store/appState.js'
import { customElement, property } from 'lit/decorators.js' import { customElement, property, state } from 'lit/decorators.js'
import './DashboardForceCurve.js' import './DashboardForceCurve.js'
import './DashboardMetric.js' import './DashboardMetric.js'
import './DashboardActions.js' import './DashboardActions.js'
import './BatteryIcon.js' import './BatteryIcon.js'
import { icon_route, icon_stopwatch, icon_bolt, icon_paddle, icon_heartbeat, icon_fire, icon_clock } from '../lib/icons.js' import './SettingsDialog'
import { icon_route, icon_stopwatch, icon_bolt, icon_paddle, icon_heartbeat, icon_fire, icon_clock, icon_settings } from '../lib/icons.js'
@customElement('performance-dashboard') @customElement('performance-dashboard')
export class PerformanceDashboard extends AppElement { export class PerformanceDashboard extends AppElement {
@ -44,7 +45,26 @@ export class PerformanceDashboard extends AppElement {
dashboard-actions { dashboard-actions {
padding: 0.5em 0 0 0; padding: 0.5em 0 0 0;
} }
.settings {
padding: 0.1em 0;
position: absolute;
bottom: 0;
right: 0;
z-index: 20;
}
.settings .icon {
cursor: pointer;
height: 1em;
}
.settings:hover .icon {
filter: brightness(150%);
}
` `
@state({ type: Object })
dialog
@property({ type: Object }) @property({ type: Object })
metrics metrics
@ -55,6 +75,10 @@ export class PerformanceDashboard extends AppElement {
render () { render () {
const metrics = this.calculateFormattedMetrics(this.appState.metrics) const metrics = this.calculateFormattedMetrics(this.appState.metrics)
return html` return html`
<div class="settings" @click=${this.openSettings}>
${icon_settings}
${this.dialog ? this.dialog : ''}
</div>
<dashboard-metric .icon=${icon_route} .unit=${metrics?.totalLinearDistanceFormatted?.unit || 'm'} .value=${metrics?.totalLinearDistanceFormatted?.value}></dashboard-metric> <dashboard-metric .icon=${icon_route} .unit=${metrics?.totalLinearDistanceFormatted?.unit || 'm'} .value=${metrics?.totalLinearDistanceFormatted?.value}></dashboard-metric>
<dashboard-metric .icon=${icon_stopwatch} unit="/500m" .value=${metrics?.cyclePaceFormatted?.value}></dashboard-metric> <dashboard-metric .icon=${icon_stopwatch} unit="/500m" .value=${metrics?.cyclePaceFormatted?.value}></dashboard-metric>
<dashboard-metric .icon=${icon_bolt} unit="watt" .value=${metrics?.cyclePower?.value}></dashboard-metric> <dashboard-metric .icon=${icon_bolt} unit="watt" .value=${metrics?.cyclePower?.value}></dashboard-metric>
@ -77,6 +101,14 @@ export class PerformanceDashboard extends AppElement {
` `
} }
openSettings () {
this.dialog = html`<settings-dialog .config=${this.appState.config.guiConfigs} @close=${dialogClosed}></settings-dialog>`
function dialogClosed (event) {
this.dialog = undefined
}
}
// todo: so far this is just a port of the formatter from the initial proof of concept client // todo: so far this is just a port of the formatter from the initial proof of concept client
// we could split this up to make it more readable and testable // we could split this up to make it more readable and testable
calculateFormattedMetrics (metrics) { calculateFormattedMetrics (metrics) {

View File

@ -0,0 +1,206 @@
'use strict'
/*
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
Component that renders the action buttons of the dashboard
*/
import { AppElement, html, css } from './AppElement.js'
import { customElement, property, queryAll } from 'lit/decorators.js'
import { icon_settings } from '../lib/icons.js'
import './AppDialog.js'
@customElement('settings-dialog')
export class DashboardActions extends AppElement {
static styles = css`
.metric-selector-feedback{
font-size: 0.4em;
padding-top: 8px;
}
.metric-selector-feedback>div {
display: grid;
grid-template-columns: repeat(4,1fr);
grid-template-rows: repeat(2, max-content);
gap: 8px;
}
.settings-dialog>div.metric-selector{
display: grid;
grid-template-columns: repeat(4,max-content);
grid-template-rows: repeat(3, max-content);
gap: 8px;
}
.settings-dialog>div>label{
font-size: 0.6em;
}
input[type="checkbox"]{
cursor: pointer;
align-self: center;
width: 1.5em;
height: 1.5em;
}
.icon {
height: 1.6em;
}
legend{
text-align: center;
}
table {
min-height: 70px;
margin-top: 8px;
width: 100%;
}
table, th, td {
font-size: 0.8em;
border: 1px solid white;
border-collapse: collapse;
}
tr {
height: 50%;
}
th, td {
padding: 8px;
text-align: center;
background-color: var(--theme-widget-color);
}
`
@property({ type: Object })
config
@queryAll('input')
inputs
static get properties () {
return {
selectedMetrics: { type: Array },
sumSelectedSlots: { type: Number },
isValid: { type: Boolean }
}
}
constructor () {
super()
this.selectedMetrics = []
this.sumSelectedSlots = 0
this.isValid = false
}
@property({ type: Object })
icon
render () {
return html`
<app-dialog class="settings-dialog" .isValid=${this.isValid} @close=${this.close}>
<legend>${icon_settings}<br/>Settings</legend>
<p>Select metrics to be shown:</p>
<div class="metric-selector">
<label for="distance">Distance</label>
<input @change=${this.toggleCheck} name="distance" size=1 type="checkbox" />
<label for="timer">Timer</label>
<input @change=${this.toggleCheck} name="timer" size=1 type="checkbox" />
<label for="pace">Pace</label>
<input @change=${this.toggleCheck} name="pace" size=1 type="checkbox" />
<label for="power">Power</label>
<input @change=${this.toggleCheck} name="power" size=1 type="checkbox" />
<label for="stk">Stroke Rate</label>
<input @change=${this.toggleCheck} name="stkRate" size=1 type="checkbox" />
<label for="totalStrokes">Total Strokes</label>
<input @change=${this.toggleCheck} name="totalStk" size=1 type="checkbox" />
<label for="calories">Calories</label>
<input @change=${this.toggleCheck} name="calories" size=1 type="checkbox" />
<label for="actions">Heart Rate</label>
<input @change=${this.toggleCheck} name="heartRate" size=1 type="checkbox" />
<label for="forceCurve">Force Curve</label>
<input @change=${this.toggleCheck} name="forceCurve" size=2 type="checkbox" />
<label for="actions">Actions</label>
<input @change=${this.toggleCheck} name="actions" size=1 type="checkbox" />
</div>
<div class="metric-selector-feedback">Slots remaining: ${8 - this.sumSelectedSlots}
<table>
${this.renderSelectedMetrics()}
</table>
</div>
</app-dialog>
`
}
firstUpdated () {
this.selectedMetrics = this.config.dashboardMetrics
this.sumSelectedSlots = this.selectedMetrics.length
if (this.sumSelectedSlots === 8) {
this.isValid = true
} else {
this.isValid = false
}
[...this.inputs].forEach(input => {
input.checked = this.selectedMetrics.find(metric => metric === input.name) !== undefined
})
}
renderSelectedMetrics () {
const selectedMetrics = [html`<tr>${[0, 1, 2, 3].map(index => html`<td style="${this.selectedMetrics[3] === this.selectedMetrics[4] && index === 3 ? 'color: red' : ''}">${this.selectedMetrics[index]}</td>`)}</tr>`]
selectedMetrics.push(html`<tr>${[4, 5, 6, 7].map(index => html`<td style="${this.selectedMetrics[3] === this.selectedMetrics[4] && index === 4 ? 'color: red' : ''}">${this.selectedMetrics[index]}</td>`)}</tr>`)
return selectedMetrics
}
toggleCheck (e) {
if ((e.target.checked && this.selectedMetrics.length < 4 && e.target.size > 1 && this.selectedMetrics.length + e.target.size > 4) || (e.target.checked && this.sumSelectedSlots + 1 > 8)) {
this.isValid = this.isFormValid()
e.target.checked = false
return
}
if (e.target.checked) {
for (let index = 0; index < e.target.size; index++) {
this.selectedMetrics = [...this.selectedMetrics, e.target.name]
}
} else {
for (let index = 0; index < e.target.size; index++) {
this.selectedMetrics.splice(this.selectedMetrics.findIndex(metric => metric === e.target.name), 1)
}
}
this.sumSelectedSlots = this.selectedMetrics.length
if (this.isFormValid()) {
this.isValid = true
} else {
this.isValid = false
}
}
isFormValid () {
return this.sumSelectedSlots === 8 && this.selectedMetrics[3] !== this.selectedMetrics[4]
}
close (event) {
this.dispatchEvent(new CustomEvent('close'))
if (event.detail === 'confirm') {
this.dispatchEvent(new CustomEvent('changeGuiSetting', {
detail: {
...this.appState,
config: {
...this.appState.config,
guiConfigs: {
dashboardMetrics: this.selectedMetrics
}
}
},
bubbles: true,
composed: true
}))
}
}
}

View File

@ -27,3 +27,4 @@ export const icon_bluetooth = svg`<svg aria-hidden="true" focusable="false" clas
export const icon_upload = svg`<svg aria-hidden="true" focusable="false" class="icon" 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.4zM393.4 288H328v112c0 8.8-7.2 16-16 16h-48c-8.8 0-16-7.2-16-16V288h-65.4c-14.3 0-21.4-17.2-11.3-27.3l105.4-105.4c6.2-6.2 16.4-6.2 22.6 0l105.4 105.4c10.1 10.1 2.9 27.3-11.3 27.3z"></path></svg>` export const icon_upload = svg`<svg aria-hidden="true" focusable="false" class="icon" 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.4zM393.4 288H328v112c0 8.8-7.2 16-16 16h-48c-8.8 0-16-7.2-16-16V288h-65.4c-14.3 0-21.4-17.2-11.3-27.3l105.4-105.4c6.2-6.2 16.4-6.2 22.6 0l105.4 105.4c10.1 10.1 2.9 27.3-11.3 27.3z"></path></svg>`
export const icon_antplus = svg`<svg id="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="536.723163841808" viewBox="0 0 380 532" aria-hidden="true" focusable="false" class="icon" role="img"><path fill="currentColor" d="M176.836 0.707 C 60.266 18.305,-16.078 120.160,3.321 232.203 C 26.151 364.067,169.680 436.811,288.977 376.981 C 437.287 302.601,434.584 89.747,284.426 18.617 C 254.109 4.256,206.179 -3.723,176.836 0.707 M229.910 16.544 C 360.710 37.096,427.877 190.879,354.055 300.782 C 274.148 419.742,97.047 408.376,33.765 280.226 C -32.417 146.205,81.393 -6.791,229.910 16.544 M176.836 66.680 C 134.648 79.679,142.046 142.642,186.099 145.521 L 194.232 146.052 200.634 162.009 C 204.154 170.786,207.236 178.475,207.481 179.096 C 207.726 179.718,205.374 181.657,202.253 183.407 C 194.503 187.753,184.428 197.342,179.661 204.911 C 174.868 212.521,176.571 212.453,158.757 205.752 L 144.068 200.227 143.344 192.293 C 138.554 139.803,61.050 143.994,63.509 196.610 C 65.127 231.232,106.117 247.599,131.274 223.668 L 135.841 219.323 152.418 225.525 L 168.995 231.727 168.554 239.542 C 164.794 306.084,254.502 335.622,292.084 280.216 C 322.809 234.919,290.211 174.246,235.028 174.021 L 227.684 173.991 220.504 155.893 L 213.324 137.796 217.881 132.852 C 245.378 103.021,215.455 54.781,176.836 66.680 M61.315 483.337 C 54.332 502.445,47.085 522.295,45.209 527.447 L 41.798 536.815 51.028 536.486 L 60.257 536.158 63.781 526.554 L 67.304 516.949 82.428 516.949 L 97.552 516.949 100.847 526.836 L 104.143 536.723 113.653 536.723 C 118.884 536.723,123.164 536.580,123.164 536.406 C 123.164 536.231,117.013 519.325,109.496 498.835 C 101.978 478.346,94.813 458.658,93.573 455.085 L 91.318 448.588 82.665 448.591 L 74.011 448.595 61.315 483.337 M138.983 492.655 L 138.983 536.723 148.003 536.723 L 157.023 536.723 157.325 508.567 L 157.627 480.410 175.019 508.567 L 192.410 536.723 200.725 536.723 L 209.040 536.723 209.040 492.655 L 209.040 448.588 200.019 448.588 L 190.999 448.588 190.697 476.878 L 190.395 505.168 173.063 476.878 L 155.731 448.588 147.357 448.588 L 138.983 448.588 138.983 492.655 M225.989 456.497 L 225.989 464.407 238.983 464.407 L 251.977 464.407 251.977 500.565 L 251.977 536.723 261.017 536.723 L 270.056 536.723 270.056 500.565 L 270.056 464.407 283.051 464.407 L 296.045 464.407 296.045 456.497 L 296.045 448.588 261.017 448.588 L 225.989 448.588 225.989 456.497 M332.957 464.030 C 332.542 464.444,332.203 469.783,332.203 475.895 L 332.203 487.006 322.034 487.006 L 311.864 487.006 311.864 494.915 L 311.864 502.825 321.994 502.825 L 332.124 502.825 332.446 514.407 L 332.768 525.989 340.395 526.323 L 348.023 526.657 348.023 514.783 L 348.023 502.910 358.475 502.585 L 368.927 502.260 368.927 494.915 L 368.927 487.571 358.475 487.246 L 348.023 486.921 348.023 475.099 L 348.023 463.277 340.866 463.277 C 336.930 463.277,333.371 463.616,332.957 464.030 M86.513 485.028 C 88.831 492.020,90.962 498.376,91.247 499.153 C 91.638 500.213,89.366 500.565,82.141 500.565 L 72.514 500.565 77.190 486.441 C 79.762 478.672,81.963 472.316,82.082 472.316 C 82.202 472.316,84.195 478.037,86.513 485.028 " ></path></g></svg>` export const icon_antplus = svg`<svg id="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="536.723163841808" viewBox="0 0 380 532" aria-hidden="true" focusable="false" class="icon" role="img"><path fill="currentColor" d="M176.836 0.707 C 60.266 18.305,-16.078 120.160,3.321 232.203 C 26.151 364.067,169.680 436.811,288.977 376.981 C 437.287 302.601,434.584 89.747,284.426 18.617 C 254.109 4.256,206.179 -3.723,176.836 0.707 M229.910 16.544 C 360.710 37.096,427.877 190.879,354.055 300.782 C 274.148 419.742,97.047 408.376,33.765 280.226 C -32.417 146.205,81.393 -6.791,229.910 16.544 M176.836 66.680 C 134.648 79.679,142.046 142.642,186.099 145.521 L 194.232 146.052 200.634 162.009 C 204.154 170.786,207.236 178.475,207.481 179.096 C 207.726 179.718,205.374 181.657,202.253 183.407 C 194.503 187.753,184.428 197.342,179.661 204.911 C 174.868 212.521,176.571 212.453,158.757 205.752 L 144.068 200.227 143.344 192.293 C 138.554 139.803,61.050 143.994,63.509 196.610 C 65.127 231.232,106.117 247.599,131.274 223.668 L 135.841 219.323 152.418 225.525 L 168.995 231.727 168.554 239.542 C 164.794 306.084,254.502 335.622,292.084 280.216 C 322.809 234.919,290.211 174.246,235.028 174.021 L 227.684 173.991 220.504 155.893 L 213.324 137.796 217.881 132.852 C 245.378 103.021,215.455 54.781,176.836 66.680 M61.315 483.337 C 54.332 502.445,47.085 522.295,45.209 527.447 L 41.798 536.815 51.028 536.486 L 60.257 536.158 63.781 526.554 L 67.304 516.949 82.428 516.949 L 97.552 516.949 100.847 526.836 L 104.143 536.723 113.653 536.723 C 118.884 536.723,123.164 536.580,123.164 536.406 C 123.164 536.231,117.013 519.325,109.496 498.835 C 101.978 478.346,94.813 458.658,93.573 455.085 L 91.318 448.588 82.665 448.591 L 74.011 448.595 61.315 483.337 M138.983 492.655 L 138.983 536.723 148.003 536.723 L 157.023 536.723 157.325 508.567 L 157.627 480.410 175.019 508.567 L 192.410 536.723 200.725 536.723 L 209.040 536.723 209.040 492.655 L 209.040 448.588 200.019 448.588 L 190.999 448.588 190.697 476.878 L 190.395 505.168 173.063 476.878 L 155.731 448.588 147.357 448.588 L 138.983 448.588 138.983 492.655 M225.989 456.497 L 225.989 464.407 238.983 464.407 L 251.977 464.407 251.977 500.565 L 251.977 536.723 261.017 536.723 L 270.056 536.723 270.056 500.565 L 270.056 464.407 283.051 464.407 L 296.045 464.407 296.045 456.497 L 296.045 448.588 261.017 448.588 L 225.989 448.588 225.989 456.497 M332.957 464.030 C 332.542 464.444,332.203 469.783,332.203 475.895 L 332.203 487.006 322.034 487.006 L 311.864 487.006 311.864 494.915 L 311.864 502.825 321.994 502.825 L 332.124 502.825 332.446 514.407 L 332.768 525.989 340.395 526.323 L 348.023 526.657 348.023 514.783 L 348.023 502.910 358.475 502.585 L 368.927 502.260 368.927 494.915 L 368.927 487.571 358.475 487.246 L 348.023 486.921 348.023 475.099 L 348.023 463.277 340.866 463.277 C 336.930 463.277,333.371 463.616,332.957 464.030 M86.513 485.028 C 88.831 492.020,90.962 498.376,91.247 499.153 C 91.638 500.213,89.366 500.565,82.141 500.565 L 72.514 500.565 77.190 486.441 C 79.762 478.672,81.963 472.316,82.082 472.316 C 82.202 472.316,84.195 478.037,86.513 485.028 " ></path></g></svg>`
export const icon_settings = svg`<svg viewBox="0 0 1000 1000" focusable="false" class="icon" role="img"><path fill="currentColor" d="M983.8,425.7c-2.3-15.3-12.9-28.1-27.5-33.3L879.2,365c-4.6-12.9-9.7-25.5-15.5-37.7l35.1-73.9c6.6-13.9,5.1-30.4-4.1-42.9c-29.6-40.3-65-75.7-105.2-105.1c-12.5-9.2-28.9-10.7-42.9-4.1l-73.9,35.1c-12.2-5.7-24.8-10.9-37.7-15.5l-27.5-77.2c-5.2-14.5-17.9-25.1-33.2-27.4c-54.3-8.3-94.4-8.3-148.8,0c-15.3,2.4-28,12.9-33.2,27.4L365,120.9c-12.9,4.6-25.5,9.7-37.7,15.5l-73.9-35.1c-13.9-6.6-30.4-5.1-42.9,4.1c-40.2,29.5-75.6,64.9-105.2,105.1c-9.2,12.5-10.7,29-4.1,42.9l35.1,73.9c-5.7,12.1-10.9,24.7-15.5,37.7l-77.2,27.5c-14.6,5.2-25.1,17.9-27.4,33.2C12,453.3,10,476.9,10,500c0,23,2,46.7,6.2,74.4c2.3,15.3,12.9,28.1,27.5,33.3l77.2,27.5c4.6,13,9.8,25.5,15.5,37.7l-35.1,73.9c-6.6,13.9-5.1,30.4,4.1,42.9c29.6,40.2,65,75.6,105.2,105.2c12.5,9.2,28.9,10.7,42.9,4.1l73.9-35.1c12.2,5.7,24.8,10.9,37.7,15.5l27.5,77.2c5.2,14.5,17.9,25.1,33.2,27.4c27.2,4.2,51.5,6.2,74.4,6.2s47.3-2,74.4-6.2c15.3-2.4,28-12.9,33.2-27.4l27.5-77.2c12.9-4.6,25.5-9.7,37.7-15.5l73.9,35.1c14,6.7,30.4,5.1,42.9-4.1c40.3-29.6,75.7-65,105.2-105.2c9.1-12.4,10.7-28.9,4.1-42.9l-35.1-73.9c5.7-12.2,10.9-24.8,15.5-37.7l77.2-27.5c14.6-5.2,25.1-17.9,27.5-33.3c4.2-27.7,6.2-51.3,6.2-74.4C990,477,988,453.3,983.8,425.7z M904,537.1l-72.4,25.8c-12.7,4.5-22.4,14.8-26.2,27.7c-6.5,21.9-15,42.6-25.3,61.5c-6.4,11.8-6.8,26-1.1,38.1l32.9,69.1c-15.9,19.1-33.4,36.6-52.5,52.5L690.2,779c-12.2-5.8-26.3-5.4-38.1,1c-19,10.3-39.7,18.8-61.6,25.3c-12.9,3.8-23.2,13.5-27.7,26.2L537.1,904c-26.3,2.7-47.8,2.7-74.1,0l-25.8-72.5c-4.5-12.6-14.8-22.4-27.7-26.2c-21.9-6.5-42.6-15-61.6-25.3c-11.8-6.5-26-6.9-38.1-1l-69.1,32.8c-19.1-15.9-36.6-33.4-52.5-52.5l32.9-69.1c5.8-12.1,5.4-26.3-1.1-38.1c-10.3-18.9-18.8-39.6-25.3-61.6c-3.8-12.9-13.6-23.2-26.2-27.6L96,537.1c-1.4-13.2-2-25.3-2-37.1s0.7-23.9,2-37l72.4-25.8c12.6-4.5,22.4-14.8,26.2-27.6c6.5-21.9,15-42.6,25.3-61.6c6.4-11.8,6.8-26,1.1-38.1l-32.9-69.1c15.9-19.1,33.5-36.7,52.5-52.5l69.1,32.8c12.1,5.8,26.3,5.4,38.1-1c19-10.3,39.7-18.8,61.6-25.3c12.9-3.8,23.2-13.6,27.7-26.2l25.8-72.5c26.1-2.7,47.6-2.7,74.1,0l25.8,72.5c4.5,12.6,14.8,22.4,27.7,26.2c21.9,6.5,42.6,15,61.6,25.3c11.8,6.5,26,6.9,38.1,1l69.1-32.8c19.1,15.9,36.6,33.4,52.5,52.5L779,309.8c-5.8,12.1-5.4,26.3,1.1,38.1c10.4,19.1,18.9,39.8,25.3,61.6c3.8,12.9,13.5,23.2,26.2,27.7l72.4,25.8c1.4,13.2,2,25.3,2,37.1C906,511.8,905.3,523.9,904,537.1z"/><path fill="currentColor" d="M500,295.7c-107.2,0-194.4,87.2-194.4,194.4S392.8,684.6,500,684.6c107.2,0,194.4-87.2,194.4-194.4S607.2,295.7,500,295.7z M500,600.6c-60.9,0-110.4-49.5-110.4-110.4c0-60.9,49.5-110.4,110.4-110.4c60.9,0,110.4,49.5,110.4,110.4C610.4,551,560.9,600.6,500,600.6z"/></svg>`