incyclist-services 1.7.113 → 1.7.114

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -617,49 +617,50 @@ let ActivityRideService = (() => {
617
617
  const avatar = (0, avatars_1.useAvatars)().get(key);
618
618
  return { position, avatar, ...a };
619
619
  });
620
- if (props.length > maxEntries) {
621
- const currentIdx = props.findIndex(a => a.title === 'current');
622
- if (currentIdx < maxEntries - 1) {
623
- const deleted = props.splice(maxEntries - 1);
624
- props.push({ title: `+${deleted.length}`, tsStart: null, distanceGap: '', timeGap: '' });
625
- }
626
- else if (currentIdx > maxEntries - 1) {
627
- if (currentIdx < props.length - 2) {
628
- const deleted = props.splice(currentIdx + 1);
629
- props.splice(maxEntries - 2, currentIdx - (maxEntries - 2));
630
- props.push({ title: `+${deleted.length}`, tsStart: null, distanceGap: '', timeGap: '' });
631
- }
632
- else if (currentIdx === props.length - 2) {
633
- props.splice(maxEntries - 2, props.length - maxEntries);
634
- }
635
- else {
636
- const keep = maxEntries - 1;
637
- const cut = props.length - maxEntries;
638
- props.splice(keep, cut);
639
- }
640
- }
641
- else if (currentIdx === props.length - 2) {
642
- props.splice(maxEntries - 2, props.length - maxEntries);
643
- }
644
- else if (currentIdx === maxEntries - 1) {
645
- const deleted = props.splice(currentIdx + 1, props.length - currentIdx);
646
- props.push({ title: `+${deleted.length}`, tsStart: null, distanceGap: '', timeGap: '' });
647
- props.splice(currentIdx - 1, 1);
648
- }
649
- }
620
+ const selected = this.selectPrevRidesRows(props, maxEntries);
650
621
  let logInfo = '';
651
622
  try {
652
623
  const buildLog = (pr) => {
653
624
  const distanceGap = typeof pr.distance === 'object' ? `${pr.distance?.value}${pr.distance?.unit}` : pr.distance;
654
625
  return `${pr.position}:${pr.avatar?.shirt}-${pr.avatar?.helmet}:${pr.title}:${pr.timeGap}:${distanceGap}`;
655
626
  };
656
- logInfo = `(${props.length}/${prevRides.length})`
657
- + props.map(buildLog).join(',');
627
+ logInfo = `(${selected.length}/${prevRides.length})`
628
+ + selected.map(buildLog).join(',');
658
629
  }
659
630
  catch {
660
631
  }
661
632
  this.logEvent({ message: 'PrevRides', prevRides: logInfo });
662
- return props;
633
+ return selected;
634
+ }
635
+ selectPrevRidesRows(props, maxEntries) {
636
+ if (props.length <= maxEntries)
637
+ return props;
638
+ const currentIdx = props.findIndex(a => a.title === 'current');
639
+ const selectedIdx = new Set();
640
+ if (maxEntries >= 3) {
641
+ selectedIdx.add(0);
642
+ selectedIdx.add(props.length - 1);
643
+ }
644
+ if (currentIdx >= 0)
645
+ selectedIdx.add(currentIdx);
646
+ let above = currentIdx - 1;
647
+ let below = currentIdx + 1;
648
+ let takeAbove = true;
649
+ while (selectedIdx.size < maxEntries && (above >= 0 || below < props.length)) {
650
+ const canAbove = above >= 0;
651
+ const canBelow = below < props.length;
652
+ const useAbove = canAbove && (takeAbove || !canBelow);
653
+ if (useAbove) {
654
+ selectedIdx.add(above);
655
+ above--;
656
+ }
657
+ else {
658
+ selectedIdx.add(below);
659
+ below++;
660
+ }
661
+ takeAbove = !takeAbove;
662
+ }
663
+ return Array.from(selectedIdx).sort((a, b) => a - b).map(i => props[i]);
663
664
  }
664
665
  getPrevActivityLog(ai, current) {
665
666
  try {
@@ -51,6 +51,7 @@ const DEFAULT_LOAD_INCREMENT = 1;
51
51
  const HINTS_WORKOUT_GESTURES_KEY = 'hints.workoutRideGestures';
52
52
  const LOAD_INCREMENT_SETTING_KEY = 'preferences.workouts.loadIncrement';
53
53
  const CORNER_WIDGET_SETTING_KEY = 'preferences.workouts.rideCornerWidget';
54
+ const DEFAULT_PREV_RIDES_VISIBLE_ROWS = 1;
54
55
  let RidePageService = (() => {
55
56
  let _classDecorators = [decorators_1.Singleton];
56
57
  let _classDescriptor;
@@ -91,6 +92,8 @@ let RidePageService = (() => {
91
92
  menuProps = null;
92
93
  isInitialized = false;
93
94
  startGateProps = null;
95
+ prevRidesVisibleRows = DEFAULT_PREV_RIDES_VISIBLE_ROWS;
96
+ prevRidesMode = 'list';
94
97
  gestureHintDismissed = false;
95
98
  viewTransition = false;
96
99
  constructor() {
@@ -344,7 +347,7 @@ let RidePageService = (() => {
344
347
  const base = this.buildBaseDisplayProps();
345
348
  const displayProps = {
346
349
  ...base,
347
- ...this.buildWorkoutOverlayProps(props),
350
+ ...this.buildWorkoutOverlayProps(props, base.prevRides),
348
351
  video: props.video,
349
352
  videos: props.videos,
350
353
  route: props.route
@@ -356,7 +359,7 @@ let RidePageService = (() => {
356
359
  const base = this.buildBaseDisplayProps();
357
360
  const displayProps = {
358
361
  ...base,
359
- ...this.buildWorkoutOverlayProps(props),
362
+ ...this.buildWorkoutOverlayProps(props, base.prevRides),
360
363
  rideView: props.rideView,
361
364
  route: props.route,
362
365
  displayObserver: props.displayObserver,
@@ -365,8 +368,8 @@ let RidePageService = (() => {
365
368
  };
366
369
  return displayProps;
367
370
  }
368
- buildWorkoutOverlayProps(props) {
369
- const cornerWidget = this.getCornerWidget();
371
+ buildWorkoutOverlayProps(props, prevRides) {
372
+ const cornerWidget = this.getCornerWidget(prevRides);
370
373
  if (!this.isWorkoutAttached() || !props?.showWorkout)
371
374
  return { workoutAttached: false, cornerWidget };
372
375
  try {
@@ -385,21 +388,32 @@ let RidePageService = (() => {
385
388
  return { workoutAttached: false, cornerWidget };
386
389
  }
387
390
  }
388
- getCornerWidget() {
391
+ getCornerWidget(prevRides) {
389
392
  try {
390
- if (!this.isWorkoutAttached())
393
+ const available = this.getCornerWidgetStates(prevRides);
394
+ if (available.length <= 1)
391
395
  return undefined;
392
- return this.getUserSettings().get(CORNER_WIDGET_SETTING_KEY, 'elevation');
396
+ const current = this.getUserSettings().get(CORNER_WIDGET_SETTING_KEY, 'elevation');
397
+ return available.includes(current) ? current : available[0];
393
398
  }
394
399
  catch (err) {
395
400
  this.logError(err, 'getCornerWidget');
396
401
  return undefined;
397
402
  }
398
403
  }
404
+ getCornerWidgetStates(prevRides) {
405
+ const states = ['elevation'];
406
+ if (this.isWorkoutAttached())
407
+ states.push('workout');
408
+ if (!!prevRides && prevRides.mode !== 'hidden')
409
+ states.push('prevRides');
410
+ return states;
411
+ }
399
412
  onToggleCornerWidget() {
400
413
  try {
414
+ const available = this.getCornerWidgetStates(this.buildPrevRides());
401
415
  const current = this.getUserSettings().get(CORNER_WIDGET_SETTING_KEY, 'elevation');
402
- const next = current === 'elevation' ? 'workout' : 'elevation';
416
+ const next = available[(available.indexOf(current) + 1) % available.length];
403
417
  this.getUserSettings().set(CORNER_WIDGET_SETTING_KEY, next);
404
418
  this.updatePageDisplay();
405
419
  }
@@ -407,6 +421,30 @@ let RidePageService = (() => {
407
421
  this.logError(err, 'onToggleCornerWidget');
408
422
  }
409
423
  }
424
+ onExpandPrevRides() {
425
+ this.setPrevRidesMode('list');
426
+ }
427
+ onCollapsePrevRides() {
428
+ this.setPrevRidesMode('condensed');
429
+ }
430
+ setPrevRidesVisibleRows(n) {
431
+ try {
432
+ this.prevRidesVisibleRows = n;
433
+ this.updatePageDisplay();
434
+ }
435
+ catch (err) {
436
+ this.logError(err, 'setPrevRidesVisibleRows');
437
+ }
438
+ }
439
+ setPrevRidesMode(mode) {
440
+ try {
441
+ this.prevRidesMode = mode;
442
+ this.updatePageDisplay();
443
+ }
444
+ catch (err) {
445
+ this.logError(err, 'setPrevRidesMode');
446
+ }
447
+ }
410
448
  async checkSecretValidity() {
411
449
  if (this.getBindings().appInfo?.getChannel() === 'mobile') {
412
450
  const secretsStatus = this.getSecretBinding()?.getSecretsStatus?.();
@@ -794,7 +832,43 @@ let RidePageService = (() => {
794
832
  startGateProps: this.startGateProps,
795
833
  gestureHint: this.buildGestureHint(startOverlayProps === null),
796
834
  loadIncrement: this.getLoadIncrement(),
797
- loadButtonMode: this.getLoadButtonMode()
835
+ loadButtonMode: this.getLoadButtonMode(),
836
+ prevRides: this.buildPrevRides()
837
+ };
838
+ }
839
+ buildPrevRides() {
840
+ try {
841
+ const rows = this.getActivityRide().getPrevRidesListDisplay(this.prevRidesVisibleRows) ?? [];
842
+ if (rows.length === 0)
843
+ return { mode: 'hidden', rows: [], hasMore: false };
844
+ const hasMore = (rows.at(-1)?.position ?? rows.length) > rows.length;
845
+ return {
846
+ mode: this.prevRidesMode,
847
+ rows: rows.map(row => this.mapPrevRidesRow(row)),
848
+ hasMore
849
+ };
850
+ }
851
+ catch (err) {
852
+ this.logError(err, 'buildPrevRides');
853
+ return { mode: 'hidden', rows: [], hasMore: false };
854
+ }
855
+ }
856
+ mapPrevRidesRow(row) {
857
+ const isCurrent = row.title === 'current';
858
+ const speed = typeof row.speed === 'object' ? row.speed?.value : row.speed;
859
+ const distanceGap = typeof row.distanceGap === 'object'
860
+ ? `${row.distanceGap.value}${row.distanceGap.unit}`
861
+ : row.distanceGap;
862
+ return {
863
+ position: row.position ?? 0,
864
+ label: isCurrent ? 'You' : row.title,
865
+ timeGap: row.timeGap,
866
+ distanceGap,
867
+ isCurrent,
868
+ avatar: row.avatar,
869
+ speed,
870
+ power: row.power,
871
+ heartrate: row.heartrate
798
872
  };
799
873
  }
800
874
  onDisplayStateUpdate(state) {
@@ -611,49 +611,50 @@ let ActivityRideService = (() => {
611
611
  const avatar = useAvatars().get(key);
612
612
  return { position, avatar, ...a };
613
613
  });
614
- if (props.length > maxEntries) {
615
- const currentIdx = props.findIndex(a => a.title === 'current');
616
- if (currentIdx < maxEntries - 1) {
617
- const deleted = props.splice(maxEntries - 1);
618
- props.push({ title: `+${deleted.length}`, tsStart: null, distanceGap: '', timeGap: '' });
619
- }
620
- else if (currentIdx > maxEntries - 1) {
621
- if (currentIdx < props.length - 2) {
622
- const deleted = props.splice(currentIdx + 1);
623
- props.splice(maxEntries - 2, currentIdx - (maxEntries - 2));
624
- props.push({ title: `+${deleted.length}`, tsStart: null, distanceGap: '', timeGap: '' });
625
- }
626
- else if (currentIdx === props.length - 2) {
627
- props.splice(maxEntries - 2, props.length - maxEntries);
628
- }
629
- else {
630
- const keep = maxEntries - 1;
631
- const cut = props.length - maxEntries;
632
- props.splice(keep, cut);
633
- }
634
- }
635
- else if (currentIdx === props.length - 2) {
636
- props.splice(maxEntries - 2, props.length - maxEntries);
637
- }
638
- else if (currentIdx === maxEntries - 1) {
639
- const deleted = props.splice(currentIdx + 1, props.length - currentIdx);
640
- props.push({ title: `+${deleted.length}`, tsStart: null, distanceGap: '', timeGap: '' });
641
- props.splice(currentIdx - 1, 1);
642
- }
643
- }
614
+ const selected = this.selectPrevRidesRows(props, maxEntries);
644
615
  let logInfo = '';
645
616
  try {
646
617
  const buildLog = (pr) => {
647
618
  const distanceGap = typeof pr.distance === 'object' ? `${pr.distance?.value}${pr.distance?.unit}` : pr.distance;
648
619
  return `${pr.position}:${pr.avatar?.shirt}-${pr.avatar?.helmet}:${pr.title}:${pr.timeGap}:${distanceGap}`;
649
620
  };
650
- logInfo = `(${props.length}/${prevRides.length})`
651
- + props.map(buildLog).join(',');
621
+ logInfo = `(${selected.length}/${prevRides.length})`
622
+ + selected.map(buildLog).join(',');
652
623
  }
653
624
  catch {
654
625
  }
655
626
  this.logEvent({ message: 'PrevRides', prevRides: logInfo });
656
- return props;
627
+ return selected;
628
+ }
629
+ selectPrevRidesRows(props, maxEntries) {
630
+ if (props.length <= maxEntries)
631
+ return props;
632
+ const currentIdx = props.findIndex(a => a.title === 'current');
633
+ const selectedIdx = new Set();
634
+ if (maxEntries >= 3) {
635
+ selectedIdx.add(0);
636
+ selectedIdx.add(props.length - 1);
637
+ }
638
+ if (currentIdx >= 0)
639
+ selectedIdx.add(currentIdx);
640
+ let above = currentIdx - 1;
641
+ let below = currentIdx + 1;
642
+ let takeAbove = true;
643
+ while (selectedIdx.size < maxEntries && (above >= 0 || below < props.length)) {
644
+ const canAbove = above >= 0;
645
+ const canBelow = below < props.length;
646
+ const useAbove = canAbove && (takeAbove || !canBelow);
647
+ if (useAbove) {
648
+ selectedIdx.add(above);
649
+ above--;
650
+ }
651
+ else {
652
+ selectedIdx.add(below);
653
+ below++;
654
+ }
655
+ takeAbove = !takeAbove;
656
+ }
657
+ return Array.from(selectedIdx).sort((a, b) => a - b).map(i => props[i]);
657
658
  }
658
659
  getPrevActivityLog(ai, current) {
659
660
  try {
@@ -48,6 +48,7 @@ const DEFAULT_LOAD_INCREMENT = 1;
48
48
  const HINTS_WORKOUT_GESTURES_KEY = 'hints.workoutRideGestures';
49
49
  const LOAD_INCREMENT_SETTING_KEY = 'preferences.workouts.loadIncrement';
50
50
  const CORNER_WIDGET_SETTING_KEY = 'preferences.workouts.rideCornerWidget';
51
+ const DEFAULT_PREV_RIDES_VISIBLE_ROWS = 1;
51
52
  let RidePageService = (() => {
52
53
  let _classDecorators = [Singleton];
53
54
  let _classDescriptor;
@@ -88,6 +89,8 @@ let RidePageService = (() => {
88
89
  menuProps = null;
89
90
  isInitialized = false;
90
91
  startGateProps = null;
92
+ prevRidesVisibleRows = DEFAULT_PREV_RIDES_VISIBLE_ROWS;
93
+ prevRidesMode = 'list';
91
94
  gestureHintDismissed = false;
92
95
  viewTransition = false;
93
96
  constructor() {
@@ -341,7 +344,7 @@ let RidePageService = (() => {
341
344
  const base = this.buildBaseDisplayProps();
342
345
  const displayProps = {
343
346
  ...base,
344
- ...this.buildWorkoutOverlayProps(props),
347
+ ...this.buildWorkoutOverlayProps(props, base.prevRides),
345
348
  video: props.video,
346
349
  videos: props.videos,
347
350
  route: props.route
@@ -353,7 +356,7 @@ let RidePageService = (() => {
353
356
  const base = this.buildBaseDisplayProps();
354
357
  const displayProps = {
355
358
  ...base,
356
- ...this.buildWorkoutOverlayProps(props),
359
+ ...this.buildWorkoutOverlayProps(props, base.prevRides),
357
360
  rideView: props.rideView,
358
361
  route: props.route,
359
362
  displayObserver: props.displayObserver,
@@ -362,8 +365,8 @@ let RidePageService = (() => {
362
365
  };
363
366
  return displayProps;
364
367
  }
365
- buildWorkoutOverlayProps(props) {
366
- const cornerWidget = this.getCornerWidget();
368
+ buildWorkoutOverlayProps(props, prevRides) {
369
+ const cornerWidget = this.getCornerWidget(prevRides);
367
370
  if (!this.isWorkoutAttached() || !props?.showWorkout)
368
371
  return { workoutAttached: false, cornerWidget };
369
372
  try {
@@ -382,21 +385,32 @@ let RidePageService = (() => {
382
385
  return { workoutAttached: false, cornerWidget };
383
386
  }
384
387
  }
385
- getCornerWidget() {
388
+ getCornerWidget(prevRides) {
386
389
  try {
387
- if (!this.isWorkoutAttached())
390
+ const available = this.getCornerWidgetStates(prevRides);
391
+ if (available.length <= 1)
388
392
  return undefined;
389
- return this.getUserSettings().get(CORNER_WIDGET_SETTING_KEY, 'elevation');
393
+ const current = this.getUserSettings().get(CORNER_WIDGET_SETTING_KEY, 'elevation');
394
+ return available.includes(current) ? current : available[0];
390
395
  }
391
396
  catch (err) {
392
397
  this.logError(err, 'getCornerWidget');
393
398
  return undefined;
394
399
  }
395
400
  }
401
+ getCornerWidgetStates(prevRides) {
402
+ const states = ['elevation'];
403
+ if (this.isWorkoutAttached())
404
+ states.push('workout');
405
+ if (!!prevRides && prevRides.mode !== 'hidden')
406
+ states.push('prevRides');
407
+ return states;
408
+ }
396
409
  onToggleCornerWidget() {
397
410
  try {
411
+ const available = this.getCornerWidgetStates(this.buildPrevRides());
398
412
  const current = this.getUserSettings().get(CORNER_WIDGET_SETTING_KEY, 'elevation');
399
- const next = current === 'elevation' ? 'workout' : 'elevation';
413
+ const next = available[(available.indexOf(current) + 1) % available.length];
400
414
  this.getUserSettings().set(CORNER_WIDGET_SETTING_KEY, next);
401
415
  this.updatePageDisplay();
402
416
  }
@@ -404,6 +418,30 @@ let RidePageService = (() => {
404
418
  this.logError(err, 'onToggleCornerWidget');
405
419
  }
406
420
  }
421
+ onExpandPrevRides() {
422
+ this.setPrevRidesMode('list');
423
+ }
424
+ onCollapsePrevRides() {
425
+ this.setPrevRidesMode('condensed');
426
+ }
427
+ setPrevRidesVisibleRows(n) {
428
+ try {
429
+ this.prevRidesVisibleRows = n;
430
+ this.updatePageDisplay();
431
+ }
432
+ catch (err) {
433
+ this.logError(err, 'setPrevRidesVisibleRows');
434
+ }
435
+ }
436
+ setPrevRidesMode(mode) {
437
+ try {
438
+ this.prevRidesMode = mode;
439
+ this.updatePageDisplay();
440
+ }
441
+ catch (err) {
442
+ this.logError(err, 'setPrevRidesMode');
443
+ }
444
+ }
407
445
  async checkSecretValidity() {
408
446
  if (this.getBindings().appInfo?.getChannel() === 'mobile') {
409
447
  const secretsStatus = this.getSecretBinding()?.getSecretsStatus?.();
@@ -791,7 +829,43 @@ let RidePageService = (() => {
791
829
  startGateProps: this.startGateProps,
792
830
  gestureHint: this.buildGestureHint(startOverlayProps === null),
793
831
  loadIncrement: this.getLoadIncrement(),
794
- loadButtonMode: this.getLoadButtonMode()
832
+ loadButtonMode: this.getLoadButtonMode(),
833
+ prevRides: this.buildPrevRides()
834
+ };
835
+ }
836
+ buildPrevRides() {
837
+ try {
838
+ const rows = this.getActivityRide().getPrevRidesListDisplay(this.prevRidesVisibleRows) ?? [];
839
+ if (rows.length === 0)
840
+ return { mode: 'hidden', rows: [], hasMore: false };
841
+ const hasMore = (rows.at(-1)?.position ?? rows.length) > rows.length;
842
+ return {
843
+ mode: this.prevRidesMode,
844
+ rows: rows.map(row => this.mapPrevRidesRow(row)),
845
+ hasMore
846
+ };
847
+ }
848
+ catch (err) {
849
+ this.logError(err, 'buildPrevRides');
850
+ return { mode: 'hidden', rows: [], hasMore: false };
851
+ }
852
+ }
853
+ mapPrevRidesRow(row) {
854
+ const isCurrent = row.title === 'current';
855
+ const speed = typeof row.speed === 'object' ? row.speed?.value : row.speed;
856
+ const distanceGap = typeof row.distanceGap === 'object'
857
+ ? `${row.distanceGap.value}${row.distanceGap.unit}`
858
+ : row.distanceGap;
859
+ return {
860
+ position: row.position ?? 0,
861
+ label: isCurrent ? 'You' : row.title,
862
+ timeGap: row.timeGap,
863
+ distanceGap,
864
+ isCurrent,
865
+ avatar: row.avatar,
866
+ speed,
867
+ power: row.power,
868
+ heartrate: row.heartrate
795
869
  };
796
870
  }
797
871
  onDisplayStateUpdate(state) {
@@ -158,6 +158,7 @@ export declare class ActivityRideService extends IncyclistService {
158
158
  onRouteUpdate(points: Array<RoutePoint>): void;
159
159
  getPrevRideStats(current: ActivityLogRecord): PastActivityInfo;
160
160
  getPrevRidesListDisplay(maxEntries?: number): Array<PrevRidesListDisplayProps>;
161
+ protected selectPrevRidesRows(props: Array<PrevRidesListDisplayProps>, maxEntries: number): Array<PrevRidesListDisplayProps>;
161
162
  protected getPrevActivityLog(ai: ActivityInfo, current: ActivityLogRecord): PastActivityLogEntry | null;
162
163
  protected getRecordWithSameOrBiggerTime(logs: any, current: any): any;
163
164
  protected calculateDistanceGap(ai: ActivityInfo, res: any, current: any): {
@@ -1,7 +1,8 @@
1
1
  import { IncyclistPageService } from "../../base/pages";
2
2
  import { CurrentRideDisplayProps, CurrentRideState, IObserver, RideType } from "../../types";
3
- import { AnyRidePageDisplayProps, GPXRidePageDisplayProps, IRidePageService, RideMenuProps, RidePageDisplayProps, StartGateProps, VideoRidePageDisplayProps, WorkoutDashboardLine, WorkoutGestureHint, WorkoutGraphActuals, WorkoutGraphPlan, WorkoutRideMenuProps, WorkoutRidePageDisplayProps, WorkoutUpcomingSteps } from "./types";
3
+ import { AnyRidePageDisplayProps, GPXRidePageDisplayProps, IRidePageService, PrevRidesRowProps, RideMenuProps, RidePageDisplayProps, StartGateProps, VideoRidePageDisplayProps, WorkoutDashboardLine, WorkoutGestureHint, WorkoutGraphActuals, WorkoutGraphPlan, WorkoutRideMenuProps, WorkoutRidePageDisplayProps, WorkoutUpcomingSteps } from "./types";
4
4
  import { ISecretBinding } from "../../api/secret";
5
+ import { PrevRidesListDisplayProps } from "../../activities";
5
6
  import type { LoadButtonMode, PowerAdjustmentResult, WorkoutDisplayProperties } from "../../workouts/ride/types";
6
7
  import type { Workout } from "../../workouts/base/model";
7
8
  import type { StepDefinition } from "../../workouts/base/model/types";
@@ -15,6 +16,8 @@ export declare class RidePageService extends IncyclistPageService implements IRi
15
16
  protected menuProps: RideMenuProps | null;
16
17
  protected isInitialized: boolean;
17
18
  protected startGateProps: StartGateProps | null;
19
+ protected prevRidesVisibleRows: number;
20
+ protected prevRidesMode: 'condensed' | 'list';
18
21
  protected gestureHintDismissed: boolean;
19
22
  protected viewTransition: boolean;
20
23
  constructor();
@@ -40,9 +43,14 @@ export declare class RidePageService extends IncyclistPageService implements IRi
40
43
  protected getGPXRideDisplayProps(): GPXRidePageDisplayProps;
41
44
  protected buildWorkoutOverlayProps(props: CurrentRideDisplayProps & {
42
45
  showWorkout?: boolean;
43
- }): Partial<RidePageDisplayProps>;
44
- protected getCornerWidget(): 'elevation' | 'workout' | undefined;
46
+ }, prevRides: RidePageDisplayProps['prevRides']): Partial<RidePageDisplayProps>;
47
+ protected getCornerWidget(prevRides: RidePageDisplayProps['prevRides']): 'elevation' | 'workout' | 'prevRides' | undefined;
48
+ protected getCornerWidgetStates(prevRides: RidePageDisplayProps['prevRides']): Array<'elevation' | 'workout' | 'prevRides'>;
45
49
  onToggleCornerWidget(): void;
50
+ onExpandPrevRides(): void;
51
+ onCollapsePrevRides(): void;
52
+ setPrevRidesVisibleRows(n: number): void;
53
+ setPrevRidesMode(mode: 'condensed' | 'list'): void;
46
54
  protected checkSecretValidity(): Promise<void>;
47
55
  protected showStartGate(): void;
48
56
  protected hideStartgate(): void;
@@ -99,7 +107,14 @@ export declare class RidePageService extends IncyclistPageService implements IRi
99
107
  gestureHint: WorkoutGestureHint;
100
108
  loadIncrement: number;
101
109
  loadButtonMode: LoadButtonMode;
110
+ prevRides: {
111
+ mode: "hidden" | "condensed" | "list";
112
+ rows: PrevRidesRowProps[];
113
+ hasMore: boolean;
114
+ };
102
115
  };
116
+ protected buildPrevRides(): RidePageDisplayProps['prevRides'];
117
+ protected mapPrevRidesRow(row: PrevRidesListDisplayProps): PrevRidesRowProps;
103
118
  protected onDisplayStateUpdate(state: CurrentRideState): void;
104
119
  protected updatePageDisplay(): void;
105
120
  protected registerHandlers(observer: IObserver | null | undefined, map: Record<string, any>): void;
@@ -4,6 +4,7 @@ import { IObserver, RideType } from "../../types";
4
4
  import { CurrentPosition, CurrentRideState, GPXStartOverlayProps, RideViewType, StartOverlayProps, StreetViewEvent, VideoDisplayProps, VideoStartOverlayProps } from "../types";
5
5
  import type { LoadButtonMode, PowerAdjustmentResult } from "../../workouts/ride/types";
6
6
  import type { WorkoutGraphPlanBar } from "../../workouts/base/graph/types";
7
+ import type { Avatar } from "../../avatars";
7
8
  export interface StartGateProps {
8
9
  title: string;
9
10
  body: string;
@@ -29,7 +30,23 @@ export interface RidePageDisplayProps {
29
30
  loadIncrement?: number;
30
31
  workoutAttached?: boolean;
31
32
  loadButtonMode?: LoadButtonMode;
32
- cornerWidget?: 'elevation' | 'workout';
33
+ cornerWidget?: 'elevation' | 'workout' | 'prevRides';
34
+ prevRides?: {
35
+ mode: 'hidden' | 'condensed' | 'list';
36
+ rows: PrevRidesRowProps[];
37
+ hasMore: boolean;
38
+ };
39
+ }
40
+ export interface PrevRidesRowProps {
41
+ position: number;
42
+ label: string;
43
+ timeGap: string;
44
+ distanceGap?: string;
45
+ isCurrent: boolean;
46
+ avatar?: Avatar;
47
+ speed?: number;
48
+ power?: number;
49
+ heartrate?: number;
33
50
  }
34
51
  export interface VideoRidePageDisplayProps extends RidePageDisplayProps {
35
52
  video?: VideoDisplayProps;
@@ -64,6 +81,8 @@ interface RidePageCallbacks {
64
81
  dontShowAgain: boolean;
65
82
  }): void;
66
83
  onToggleCornerWidget(): void;
84
+ onExpandPrevRides?(): void;
85
+ onCollapsePrevRides?(): void;
67
86
  }
68
87
  export interface IRidePageService extends RidePageCallbacks, IPageService {
69
88
  initPage(): Promise<RideType | undefined>;
@@ -75,6 +94,8 @@ export interface IRidePageService extends RidePageCallbacks, IPageService {
75
94
  adjustLoad(deltaPct: number): PowerAdjustmentResult | undefined;
76
95
  getLoadButtonMode(): LoadButtonMode;
77
96
  isWorkoutAttached(): boolean;
97
+ setPrevRidesVisibleRows(n: number): void;
98
+ setPrevRidesMode(mode: 'condensed' | 'list'): void;
78
99
  }
79
100
  export interface WorkoutGraphPoint {
80
101
  x: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-services",
3
- "version": "1.7.113",
3
+ "version": "1.7.114",
4
4
  "peerDependencies": {
5
5
  "gd-eventlog": "^0.1.27"
6
6
  },