Skip to content

Commit 0772026

Browse files
cagnuleinclaude
andauthored
Add speed and inclination +/- buttons to floating template (#4258)
* Add speed and inclination +/- buttons to floating template Add new control tiles for speed and inclination in the floating template (both vertical and horizontal variants). These tiles display the current value with +/- buttons for adjustment, useful for treadmill users who want to control speed and incline from the floating overlay. Changes: - Add speedcontrol and inclinecontrol tiles to floating.htm and hfloating.htm - Add SpeedPlus/SpeedMinus and InclinationPlus/InclinationMinus JavaScript functions - Add WebSocket message handlers (speed_plus, speed_minus, inclination_plus, inclination_minus) - Add corresponding signals and slots in templateinfosenderbuilder and homeform - Wire up to existing Plus/Minus functions which handle speed and inclination changes https://claude.ai/code/session_01QgLyRenM7sSWqqGU1Esy3s * Integrate speed/inclination buttons into existing rows Replace AVG/MAX labels with -/+ buttons on speed and inclination rows instead of having separate control tiles. This provides a cleaner UI where users can see all metrics (avg, current, max) while also having control buttons on the same row. Layout: [-] AVG_VALUE | CURRENT_VALUE | [+] MAX_VALUE https://claude.ai/code/session_01QgLyRenM7sSWqqGU1Esy3s * Add AVG/MAX labels under values in speed/inclination rows Add small labels under the avg and max values so users know what the values represent. Layout is now: [-] avg_value | current_value | [+] max_value AVG MAX https://claude.ai/code/session_01QgLyRenM7sSWqqGU1Esy3s * Show speed/inclination +/- buttons only for treadmills The +/- control buttons on speed and inclination rows are now only visible when connected to a treadmill device. For other device types (bike, elliptical, etc.), the standard AVG/MAX labels are shown instead. Uses deviceType and TREADMILL_TYPE from workout data to detect the device type and toggle visibility via CSS classes. https://claude.ai/code/session_01QgLyRenM7sSWqqGU1Esy3s * Fix table layout consistency for non-treadmill devices Wrap the <br> and AVG/MAX label elements together in a span with the treadmill-only class so they are both hidden for non-treadmill devices. This ensures the table layout is identical to the original for bikes and other non-treadmill equipment. https://claude.ai/code/session_01QgLyRenM7sSWqqGU1Esy3s --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 5bd7426 commit 0772026

6 files changed

Lines changed: 268 additions & 25 deletions

File tree

src/homeform.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,10 @@ homeform::homeform(QQmlApplicationEngine *engine, bluetooth *bl) {
558558
&homeform::pelotonOffset_Minus);
559559
connect(this->innerTemplateManager, &TemplateInfoSenderBuilder::gears_Plus, this, &homeform::gearUp);
560560
connect(this->innerTemplateManager, &TemplateInfoSenderBuilder::gears_Minus, this, &homeform::gearDown);
561+
connect(this->innerTemplateManager, &TemplateInfoSenderBuilder::speed_Plus, this, &homeform::speedPlus);
562+
connect(this->innerTemplateManager, &TemplateInfoSenderBuilder::speed_Minus, this, &homeform::speedMinus);
563+
connect(this->innerTemplateManager, &TemplateInfoSenderBuilder::inclination_Plus, this, &homeform::inclinationPlus);
564+
connect(this->innerTemplateManager, &TemplateInfoSenderBuilder::inclination_Minus, this, &homeform::inclinationMinus);
561565
connect(this->innerTemplateManager, &TemplateInfoSenderBuilder::pelotonOffset, this, &homeform::pelotonOffset);
562566
connect(this->innerTemplateManager, &TemplateInfoSenderBuilder::pelotonAskStart, this, &homeform::pelotonAskStart);
563567
connect(this->innerTemplateManager, &TemplateInfoSenderBuilder::peloton_start_workout, this,
@@ -1610,6 +1614,22 @@ void homeform::gearDown() {
16101614
}
16111615
}
16121616

1617+
void homeform::speedPlus() {
1618+
Plus(QStringLiteral("speed"));
1619+
}
1620+
1621+
void homeform::speedMinus() {
1622+
Minus(QStringLiteral("speed"));
1623+
}
1624+
1625+
void homeform::inclinationPlus() {
1626+
Plus(QStringLiteral("inclination"));
1627+
}
1628+
1629+
void homeform::inclinationMinus() {
1630+
Minus(QStringLiteral("inclination"));
1631+
}
1632+
16131633
void homeform::ftmsAccessoryConnected(smartspin2k *d) {
16141634
connect(this, &homeform::autoResistanceChanged, d, &smartspin2k::autoResistanceChanged);
16151635
connect(d, &smartspin2k::gearUp, this, &homeform::gearUp);

src/homeform.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,10 @@ class homeform : public QObject {
10561056
void sortTilesTimeout();
10571057
void gearUp();
10581058
void gearDown();
1059+
void speedPlus();
1060+
void speedMinus();
1061+
void inclinationPlus();
1062+
void inclinationMinus();
10591063
void changeTimestamp(QTime source, QTime actual);
10601064
void pelotonOffset_Plus();
10611065
void pelotonOffset_Minus();

src/inner_templates/floating/floating.htm

Lines changed: 93 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
font-size: 24px;
4040
}
4141

42+
.treadmill-only {
43+
display: none;
44+
}
45+
4246
.overlay {
4347
position: absolute;
4448
top: 0;
@@ -73,20 +77,24 @@ <h2 style="color: #FFFFFF; font-family: sans-serif">Peloton Workout in progress!
7377
<tr class="speed" sort-order="0">
7478
<td class="icon">🏃</td>
7579
<td style="text-align: left">SPEED</td>
76-
<td class="speed-avg-title"><small>AVG</small></td>
77-
<td class="speed-avg">0.0</td>
80+
<td class="speed-avg-title"><small class="non-treadmill">AVG</small><button class="treadmill-only" style="width: 30px; font-size: 18px; color: white; background-color:#4C70BF; border: none; cursor: pointer;"
81+
onclick="SpeedMinus()">-</button></td>
82+
<td class="speed-avg"><span class="speed-avg-value">0.0</span><span class="treadmill-only"><br><small style="font-size: 10px; color: #888;">AVG</small></span></td>
7883
<td class="speed-value values"><b>0.0</b></td>
79-
<td class="speed-max-title"><small>MAX</small></td>
80-
<td class="speed-max">0.0</td>
84+
<td class="speed-max-title"><small class="non-treadmill">MAX</small><button class="treadmill-only" style="width: 30px; font-size: 18px; color: white; background-color:#4C70BF; border: none; cursor: pointer;"
85+
onclick="SpeedPlus()">+</button></td>
86+
<td class="speed-max"><span class="speed-max-value">0.0</span><span class="treadmill-only"><br><small style="font-size: 10px; color: #888;">MAX</small></span></td>
8187
</tr>
8288
<tr class="inclination" sort-order="1">
8389
<td class="icon">📐</td>
8490
<td style="text-align: left">INCLINE</td>
85-
<td><small>AVG</small></td>
86-
<td class="inclination-avg">0.0</td>
91+
<td class="inclination-avg-title"><small class="non-treadmill">AVG</small><button class="treadmill-only" style="width: 30px; font-size: 18px; color: white; background-color:#4C70BF; border: none; cursor: pointer;"
92+
onclick="InclinationMinus()">-</button></td>
93+
<td class="inclination-avg"><span class="inclination-avg-value">0.0</span><span class="treadmill-only"><br><small style="font-size: 10px; color: #888;">AVG</small></span></td>
8794
<td class="inclination-value values"><b>0.0</b></td>
88-
<td><small>MAX</small></td>
89-
<td class="inclination-max">0.0</td>
95+
<td class="inclination-max-title"><small class="non-treadmill">MAX</small><button class="treadmill-only" style="width: 30px; font-size: 18px; color: white; background-color:#4C70BF; border: none; cursor: pointer;"
96+
onclick="InclinationPlus()">+</button></td>
97+
<td class="inclination-max"><span class="inclination-max-value">0.0</span><span class="treadmill-only"><br><small style="font-size: 10px; color: #888;">MAX</small></span></td>
9098
</tr>
9199
<tr class="pace" sort-order="2">
92100
<td class="icon">🏃</td>
@@ -306,6 +314,62 @@ <h2 style="color: #FFFFFF; font-family: sans-serif">Peloton Workout in progress!
306314
});
307315
}
308316

317+
function SpeedPlus() {
318+
let el = new MainWSQueueElement({
319+
msg: 'speed_plus',
320+
}, function (msg) {
321+
if (msg.msg === 'R_speed_plus') {
322+
return msg.content;
323+
}
324+
return null;
325+
}, 15000, 1);
326+
el.enqueue().catch(function (err) {
327+
console.error('Error is ' + err);
328+
});
329+
}
330+
331+
function SpeedMinus() {
332+
let el = new MainWSQueueElement({
333+
msg: 'speed_minus',
334+
}, function (msg) {
335+
if (msg.msg === 'R_speed_minus') {
336+
return msg.content;
337+
}
338+
return null;
339+
}, 15000, 1);
340+
el.enqueue().catch(function (err) {
341+
console.error('Error is ' + err);
342+
});
343+
}
344+
345+
function InclinationPlus() {
346+
let el = new MainWSQueueElement({
347+
msg: 'inclination_plus',
348+
}, function (msg) {
349+
if (msg.msg === 'R_inclination_plus') {
350+
return msg.content;
351+
}
352+
return null;
353+
}, 15000, 1);
354+
el.enqueue().catch(function (err) {
355+
console.error('Error is ' + err);
356+
});
357+
}
358+
359+
function InclinationMinus() {
360+
let el = new MainWSQueueElement({
361+
msg: 'inclination_minus',
362+
}, function (msg) {
363+
if (msg.msg === 'R_inclination_minus') {
364+
return msg.content;
365+
}
366+
return null;
367+
}, 15000, 1);
368+
el.enqueue().catch(function (err) {
369+
console.error('Error is ' + err);
370+
});
371+
}
372+
309373
function Lap() {
310374
let el = new MainWSQueueElement({
311375
msg: 'lap',
@@ -611,6 +675,7 @@ <h2 style="color: #FFFFFF; font-family: sans-serif">Peloton Workout in progress!
611675
'speed_color', 'pace_color', 'power_zone_color', 'target_power_zone_color', 'cadence_color', 'heart_color', 'watts_color',
612676
'peloton_resistance_color', 'target_resistance', 'target_peloton_resistance',
613677
'target_cadence', 'target_power', 'peloton_offset', 'peloton_ask_start', 'target_speed', 'target_pace_h', 'target_pace_m', 'target_pace_s',
678+
'deviceType', 'TREADMILL_TYPE',
614679
'inclination', 'inclination_lapavg',
615680
'inclination_lapmax', 'target_inclination', 'power_zone', 'power_zone_lapavg', 'power_zone_lapmax', 'target_power_zone', 'jouls',
616681
'row_remaining_time_s', 'row_remaining_time_m', 'row_remaining_time_h' , 'autoresistance', 'gears', 'elevation', 'pace_s' , 'pace_m',
@@ -673,6 +738,8 @@ <h2 style="color: #FFFFFF; font-family: sans-serif">Peloton Workout in progress!
673738
var peloton_offset = 0;
674739
var gears = 0;
675740
var nextrow = "";
741+
var deviceType = -1;
742+
var TREADMILL_TYPE = -1;
676743

677744
for (let key of keys_arr) {
678745
if (msg.content[key] === undefined || msg.content[key] === null)
@@ -789,6 +856,10 @@ <h2 style="color: #FFFFFF; font-family: sans-serif">Peloton Workout in progress!
789856
peloton_offset = msg.content[key];
790857
} else if (key === 'gears') {
791858
gears = msg.content[key];
859+
} else if (key === 'deviceType') {
860+
deviceType = msg.content[key];
861+
} else if (key === 'TREADMILL_TYPE') {
862+
TREADMILL_TYPE = msg.content[key];
792863
} else if (key === 'peloton_resistance_color') {
793864
$('.pelotonresistance-value').css('color', msg.content[key]);
794865
} else if (key === 'heart_color') {
@@ -837,14 +908,24 @@ <h2 style="color: #FFFFFF; font-family: sans-serif">Peloton Workout in progress!
837908

838909
$('.speed-value').html("<b>" + speed.toFixed(1) + "</b>");
839910
}
840-
$('.speed-avg').html(speed_lapavg.toFixed(1));
841-
$('.speed-max').html(speed_lapmax.toFixed(1));
911+
$('.speed-avg-value').html(speed_lapavg.toFixed(1));
912+
$('.speed-max-value').html(speed_lapmax.toFixed(1));
842913
if (tile_target_inclination_enabled && target_inclination > 0)
843914
$('.inclination-value').html("<b>" + inclination.toFixed(1) + "/" + target_inclination.toFixed(1) + "</b>");
844915
else
845916
$('.inclination-value').html("<b>" + inclination.toFixed(1) + "</b>");
846-
$('.inclination-avg').html(inclination_lapavg.toFixed(1));
847-
$('.inclination-max').html(inclination_lapmax.toFixed(1));
917+
$('.inclination-avg-value').html(inclination_lapavg.toFixed(1));
918+
$('.inclination-max-value').html(inclination_lapmax.toFixed(1));
919+
920+
// Show/hide treadmill-only controls based on device type
921+
if (deviceType === TREADMILL_TYPE && TREADMILL_TYPE !== -1) {
922+
$('.treadmill-only').show();
923+
$('.non-treadmill').hide();
924+
} else {
925+
$('.treadmill-only').hide();
926+
$('.non-treadmill').show();
927+
}
928+
848929
$('.elevation-value').html("<b>" + elevation.toFixed(1) + "</b>");
849930
if (tile_target_cadence_enabled && target_cadence > 0)
850931
$('.cadence-value').html("<b>" + cadence.toFixed(0) + "/" + target_cadence.toFixed(0) + "</b>");

0 commit comments

Comments
 (0)