incyclist-services 1.7.121 → 1.7.125

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.
@@ -356,15 +356,16 @@ let ActiveRidesService = (() => {
356
356
  };
357
357
  displayProps.push(displayItem);
358
358
  });
359
+ const diffValue = (r) => r.diffDistance?.value ?? 0;
359
360
  if (displayProps.length > this.maxLength) {
360
- const absDiff = (r) => Math.abs(r.diffDistance);
361
+ const absDiff = (r) => Math.abs(diffValue(r));
361
362
  displayProps.sort((a, b) => {
362
363
  return absDiff(b) > absDiff(a) ? -1 : 1;
363
364
  });
364
365
  return displayProps.filter((_r, idx) => idx < this.maxLength);
365
366
  }
366
367
  displayProps.sort((a, b) => {
367
- return b.diffDistance > a.diffDistance ? -1 : 1;
368
+ return diffValue(b) > diffValue(a) ? -1 : 1;
368
369
  });
369
370
  return displayProps;
370
371
  }
@@ -428,6 +428,7 @@ let ActivityRideService = (() => {
428
428
  const isFreeRide = startSettings?.type === 'Free-Ride';
429
429
  const showWorkoutSummary = this.activity?.routeType === 'None';
430
430
  const showSave = this.activity !== undefined && !this.isSaveDone;
431
+ const showDelete = this.activity !== undefined && !this.isSaveDone;
431
432
  const showContinue = this.state !== 'completed';
432
433
  const hasGPX = this.activity?.logs?.some((log) => !!log.lat && !!log.lng);
433
434
  const showMap = hasGPX || isFreeRide || (route?.description?.hasGpx);
@@ -440,6 +441,7 @@ let ActivityRideService = (() => {
440
441
  const props = {
441
442
  activity: (0, utils_3.createUIActivityDetails)(this.activity),
442
443
  showSave,
444
+ showDelete,
443
445
  showContinue,
444
446
  showMap,
445
447
  showWorkoutSummary,
@@ -59,6 +59,7 @@ let IncyclistBindings = (() => {
59
59
  downloadManager;
60
60
  form;
61
61
  secret;
62
+ mapAvailability;
62
63
  mq;
63
64
  ui;
64
65
  settings;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -209,9 +209,6 @@ let DevicePairingService = (() => {
209
209
  this.logEvent({ message: 'Stop Pairing (OK)', stillPairing, stillScanning });
210
210
  try {
211
211
  this.pauseAdapters(adapters.filter(a => !adapterFilter.includes(a.udid)));
212
- if (this.isPairing()) {
213
- this.removePairingCallbacks();
214
- }
215
212
  if (this.isScanning()) {
216
213
  this.state.stopRequested = true;
217
214
  await this._stop();
@@ -220,7 +217,9 @@ let DevicePairingService = (() => {
220
217
  this.settings = {};
221
218
  this.state.initialized = false;
222
219
  this.state.waiting = false;
223
- this.state.check = null;
220
+ if (!stillPairing) {
221
+ this.state.check = null;
222
+ }
224
223
  this.state.scan = null;
225
224
  this.state.stopRequested = false;
226
225
  this.state.stopped = true;
@@ -1011,6 +1010,9 @@ let DevicePairingService = (() => {
1011
1010
  this.emit('pairing-done');
1012
1011
  return;
1013
1012
  }
1013
+ if (this.isPairing() && this.state.check?.promise !== undefined) {
1014
+ return;
1015
+ }
1014
1016
  if (this.usage !== 'page' && this.isPairing()) {
1015
1017
  return;
1016
1018
  }
@@ -46,6 +46,7 @@ const SV_UPDATE_FREQ = 3000;
46
46
  const SV_MIN_READY = 1500;
47
47
  const SV_MIN_DELAY = 1000;
48
48
  const SV_START_TIMEOUT = 15000;
49
+ const SAT_START_TIMEOUT = 15000;
49
50
  let GpxDisplayService = (() => {
50
51
  let _classSuper = RouteDisplayService_1.RouteDisplayService;
51
52
  let _instanceExtraInitializers = [];
@@ -76,6 +77,8 @@ let GpxDisplayService = (() => {
76
77
  updateDurations = [];
77
78
  svStartTimedOut = false;
78
79
  svStartTimeout;
80
+ satStartTimedOut = false;
81
+ satStartTimeout;
79
82
  constructor() {
80
83
  super();
81
84
  }
@@ -90,6 +93,10 @@ let GpxDisplayService = (() => {
90
93
  if (this.waitsForStreetView())
91
94
  this.armStreetViewStartTimeout();
92
95
  }
96
+ else if (rideView === 'sat') {
97
+ if (this.waitsForSatelliteView())
98
+ this.armSatelliteViewStartTimeout();
99
+ }
93
100
  }
94
101
  catch (err) {
95
102
  this.logError(err, 'initView');
@@ -114,7 +121,12 @@ let GpxDisplayService = (() => {
114
121
  return props;
115
122
  }
116
123
  getInitialStreetViewPosition() {
117
- const position = this.position;
124
+ return this.enrichWithHeading(this.position, 'getInitialStreetViewPosition');
125
+ }
126
+ getSatelliteViewPosition() {
127
+ return this.enrichWithHeading(this.position, 'getSatelliteViewPosition');
128
+ }
129
+ enrichWithHeading(position, logContext) {
118
130
  if (!position)
119
131
  return undefined;
120
132
  if (position.heading !== undefined)
@@ -123,17 +135,20 @@ let GpxDisplayService = (() => {
123
135
  return { ...position, heading: (0, routes_1.getHeading)(this.getOriginalRoute(), position) };
124
136
  }
125
137
  catch (err) {
126
- this.logError(err, 'getInitialStreetViewPosition');
138
+ this.logError(err, logContext);
127
139
  return position;
128
140
  }
129
141
  }
130
142
  waitsForStreetView() {
131
143
  return this.isMobile() && this.getRideSettingsDisplay().getRideView() === 'sv';
132
144
  }
145
+ waitsForSatelliteView() {
146
+ return this.isMobile() && this.getRideSettingsDisplay().getRideView() === 'sat';
147
+ }
133
148
  getSatelliteViewProps() {
134
149
  return {
135
150
  onDisplayEvent: this.onSatelliteViewEvent.bind(this),
136
- displayPosition: this.position
151
+ displayPosition: this.getSatelliteViewPosition()
137
152
  };
138
153
  }
139
154
  getMapViewProps() {
@@ -145,7 +160,7 @@ let GpxDisplayService = (() => {
145
160
  }
146
161
  getStartOverlayProps() {
147
162
  const rideView = this.getRideSettingsDisplay().getRideView();
148
- if (rideView === 'map' || (this.isMobile() && !this.waitsForStreetView())) {
163
+ if (rideView === 'map' || (this.isMobile() && !this.waitsForStreetView() && !this.waitsForSatelliteView())) {
149
164
  return {
150
165
  mapType: this.getRideViewName(),
151
166
  mapState: 'Loaded'
@@ -159,11 +174,11 @@ let GpxDisplayService = (() => {
159
174
  }
160
175
  isStartRideCompleted() {
161
176
  const rideView = this.getRideSettingsDisplay().getRideView();
162
- if (rideView === 'map' || (this.isMobile() && !this.waitsForStreetView())) {
177
+ if (rideView === 'map' || (this.isMobile() && !this.waitsForStreetView() && !this.waitsForSatelliteView())) {
163
178
  this.mapLoaded = true;
164
179
  return true;
165
180
  }
166
- if (this.svStartTimedOut)
181
+ if (this.svStartTimedOut || this.satStartTimedOut)
167
182
  return true;
168
183
  return this.mapLoaded;
169
184
  }
@@ -199,6 +214,7 @@ let GpxDisplayService = (() => {
199
214
  onSatelliteViewEvent(state, error) {
200
215
  if (state === 'Loaded') {
201
216
  this.mapLoaded = true;
217
+ this.clearSatelliteViewStartTimeout();
202
218
  }
203
219
  else if (state === 'Error') {
204
220
  this.logEvent({ message: 'sat view error', error: this.mapError });
@@ -288,12 +304,35 @@ let GpxDisplayService = (() => {
288
304
  getStreetViewStartTimeout() {
289
305
  return this.getNumSetting('SV_START_TIMEOUT') ?? SV_START_TIMEOUT;
290
306
  }
307
+ armSatelliteViewStartTimeout() {
308
+ this.clearSatelliteViewStartTimeout();
309
+ const timeout = this.getSatelliteViewStartTimeout();
310
+ this.satStartTimeout = setTimeout(() => {
311
+ this.satStartTimeout = undefined;
312
+ if (this.mapLoaded)
313
+ return;
314
+ this.satStartTimedOut = true;
315
+ this.logEvent({ message: 'satellite view start timeout', timeout });
316
+ this.emit('state-update');
317
+ }, timeout);
318
+ }
319
+ clearSatelliteViewStartTimeout() {
320
+ if (this.satStartTimeout) {
321
+ clearTimeout(this.satStartTimeout);
322
+ this.satStartTimeout = undefined;
323
+ }
324
+ }
325
+ getSatelliteViewStartTimeout() {
326
+ return this.getNumSetting('SAT_START_TIMEOUT') ?? SAT_START_TIMEOUT;
327
+ }
291
328
  onStarted() {
292
329
  this.clearStreetViewStartTimeout();
330
+ this.clearSatelliteViewStartTimeout();
293
331
  super.onStarted();
294
332
  }
295
333
  async stop() {
296
334
  this.clearStreetViewStartTimeout();
335
+ this.clearSatelliteViewStartTimeout();
297
336
  return super.stop();
298
337
  }
299
338
  getStreetViewObserver() {
@@ -416,6 +416,8 @@ let RouteCard = (() => {
416
416
  }
417
417
  updateStartPos(p, data) {
418
418
  const [C, U] = (0, i18n_1.getUnitConversionShortcuts)();
419
+ if (p === undefined || p === null)
420
+ return null;
419
421
  let value;
420
422
  if (typeof p === 'number')
421
423
  value = p;
@@ -40,6 +40,10 @@ const decorators_1 = require("../../../base/decorators");
40
40
  const service_1 = require("../../../base/service");
41
41
  const types_1 = require("../../../base/types");
42
42
  const service_2 = require("../../service");
43
+ const UNAVAILABLE_MESSAGES = {
44
+ 'need.playservices': 'Install Google Play Services to use this view',
45
+ };
46
+ const DEFAULT_UNAVAILABLE_MESSAGE = 'This view is currently unavailable on your device';
43
47
  let RideSettingsDisplayService = (() => {
44
48
  let _classDecorators = [decorators_1.Singleton];
45
49
  let _classDescriptor;
@@ -83,8 +87,6 @@ let RideSettingsDisplayService = (() => {
83
87
  };
84
88
  }
85
89
  setRideView(rideView) {
86
- if (this.isRestricted())
87
- return;
88
90
  try {
89
91
  this.getUserSettings().set('preferences.rideView', rideView);
90
92
  }
@@ -97,29 +99,29 @@ let RideSettingsDisplayService = (() => {
97
99
  this.observer.emit('changed', this.getDisplayProps());
98
100
  }
99
101
  getRideView() {
100
- if (this.isRestricted())
101
- return 'map';
102
102
  const rideView = this.getUserSettings().get('preferences.rideView', 'sv');
103
+ const availability = this.getBindings().mapAvailability?.isAvailable(rideView);
104
+ if (availability?.status === 'unavailable' || availability?.status === 'not-supported')
105
+ return 'map';
103
106
  return rideView;
104
107
  }
105
108
  getRideViewOptions() {
106
109
  const map = new Map();
107
- if (this.isRestricted()) {
108
- map.set('map', 'Map');
109
- return map;
110
- }
111
- map.set('sv', 'Street View');
112
- map.set('map', 'Map');
113
- if (!this.isMobile())
114
- map.set('sat', 'Satellite View');
110
+ this.addRideViewOption(map, 'sv', 'Street View');
111
+ map.set('map', { label: 'Map' });
112
+ this.addRideViewOption(map, 'sat', 'Satellite View');
115
113
  return map;
116
114
  }
117
- isRestricted() {
118
- if (this.isMobile()) {
119
- const secretsStatus = this.getSecretBinding()?.getSecretsStatus?.();
120
- return (secretsStatus === 'stale' || secretsStatus === 'missing' || secretsStatus === undefined);
115
+ addRideViewOption(map, key, label) {
116
+ const availability = this.getBindings().mapAvailability?.isAvailable(key);
117
+ if (availability?.status === 'not-supported')
118
+ return;
119
+ if (availability?.status === 'unavailable') {
120
+ const message = UNAVAILABLE_MESSAGES[availability.messageKey ?? ''] ?? DEFAULT_UNAVAILABLE_MESSAGE;
121
+ map.set(key, { label, disabled: true, message });
122
+ return;
121
123
  }
122
- return false;
124
+ map.set(key, { label });
123
125
  }
124
126
  isMobile() {
125
127
  return this.getBindings().appInfo?.getChannel() === 'mobile';
@@ -136,9 +138,6 @@ let RideSettingsDisplayService = (() => {
136
138
  getBindings() {
137
139
  return (0, api_1.getBindings)();
138
140
  }
139
- getSecretBinding() {
140
- return this.getBindings().secret;
141
- }
142
141
  };
143
142
  return RideSettingsDisplayService = _classThis;
144
143
  })();
@@ -353,15 +353,16 @@ let ActiveRidesService = (() => {
353
353
  };
354
354
  displayProps.push(displayItem);
355
355
  });
356
+ const diffValue = (r) => r.diffDistance?.value ?? 0;
356
357
  if (displayProps.length > this.maxLength) {
357
- const absDiff = (r) => Math.abs(r.diffDistance);
358
+ const absDiff = (r) => Math.abs(diffValue(r));
358
359
  displayProps.sort((a, b) => {
359
360
  return absDiff(b) > absDiff(a) ? -1 : 1;
360
361
  });
361
362
  return displayProps.filter((_r, idx) => idx < this.maxLength);
362
363
  }
363
364
  displayProps.sort((a, b) => {
364
- return b.diffDistance > a.diffDistance ? -1 : 1;
365
+ return diffValue(b) > diffValue(a) ? -1 : 1;
365
366
  });
366
367
  return displayProps;
367
368
  }
@@ -422,6 +422,7 @@ let ActivityRideService = (() => {
422
422
  const isFreeRide = startSettings?.type === 'Free-Ride';
423
423
  const showWorkoutSummary = this.activity?.routeType === 'None';
424
424
  const showSave = this.activity !== undefined && !this.isSaveDone;
425
+ const showDelete = this.activity !== undefined && !this.isSaveDone;
425
426
  const showContinue = this.state !== 'completed';
426
427
  const hasGPX = this.activity?.logs?.some((log) => !!log.lat && !!log.lng);
427
428
  const showMap = hasGPX || isFreeRide || (route?.description?.hasGpx);
@@ -434,6 +435,7 @@ let ActivityRideService = (() => {
434
435
  const props = {
435
436
  activity: createUIActivityDetails(this.activity),
436
437
  showSave,
438
+ showDelete,
437
439
  showContinue,
438
440
  showMap,
439
441
  showWorkoutSummary,
@@ -56,6 +56,7 @@ let IncyclistBindings = (() => {
56
56
  downloadManager;
57
57
  form;
58
58
  secret;
59
+ mapAvailability;
59
60
  mq;
60
61
  ui;
61
62
  settings;
@@ -0,0 +1 @@
1
+ export {};
@@ -203,9 +203,6 @@ let DevicePairingService = (() => {
203
203
  this.logEvent({ message: 'Stop Pairing (OK)', stillPairing, stillScanning });
204
204
  try {
205
205
  this.pauseAdapters(adapters.filter(a => !adapterFilter.includes(a.udid)));
206
- if (this.isPairing()) {
207
- this.removePairingCallbacks();
208
- }
209
206
  if (this.isScanning()) {
210
207
  this.state.stopRequested = true;
211
208
  await this._stop();
@@ -214,7 +211,9 @@ let DevicePairingService = (() => {
214
211
  this.settings = {};
215
212
  this.state.initialized = false;
216
213
  this.state.waiting = false;
217
- this.state.check = null;
214
+ if (!stillPairing) {
215
+ this.state.check = null;
216
+ }
218
217
  this.state.scan = null;
219
218
  this.state.stopRequested = false;
220
219
  this.state.stopped = true;
@@ -1005,6 +1004,9 @@ let DevicePairingService = (() => {
1005
1004
  this.emit('pairing-done');
1006
1005
  return;
1007
1006
  }
1007
+ if (this.isPairing() && this.state.check?.promise !== undefined) {
1008
+ return;
1009
+ }
1008
1010
  if (this.usage !== 'page' && this.isPairing()) {
1009
1011
  return;
1010
1012
  }
@@ -43,6 +43,7 @@ const SV_UPDATE_FREQ = 3000;
43
43
  const SV_MIN_READY = 1500;
44
44
  const SV_MIN_DELAY = 1000;
45
45
  const SV_START_TIMEOUT = 15000;
46
+ const SAT_START_TIMEOUT = 15000;
46
47
  let GpxDisplayService = (() => {
47
48
  let _classSuper = RouteDisplayService;
48
49
  let _instanceExtraInitializers = [];
@@ -73,6 +74,8 @@ let GpxDisplayService = (() => {
73
74
  updateDurations = [];
74
75
  svStartTimedOut = false;
75
76
  svStartTimeout;
77
+ satStartTimedOut = false;
78
+ satStartTimeout;
76
79
  constructor() {
77
80
  super();
78
81
  }
@@ -87,6 +90,10 @@ let GpxDisplayService = (() => {
87
90
  if (this.waitsForStreetView())
88
91
  this.armStreetViewStartTimeout();
89
92
  }
93
+ else if (rideView === 'sat') {
94
+ if (this.waitsForSatelliteView())
95
+ this.armSatelliteViewStartTimeout();
96
+ }
90
97
  }
91
98
  catch (err) {
92
99
  this.logError(err, 'initView');
@@ -111,7 +118,12 @@ let GpxDisplayService = (() => {
111
118
  return props;
112
119
  }
113
120
  getInitialStreetViewPosition() {
114
- const position = this.position;
121
+ return this.enrichWithHeading(this.position, 'getInitialStreetViewPosition');
122
+ }
123
+ getSatelliteViewPosition() {
124
+ return this.enrichWithHeading(this.position, 'getSatelliteViewPosition');
125
+ }
126
+ enrichWithHeading(position, logContext) {
115
127
  if (!position)
116
128
  return undefined;
117
129
  if (position.heading !== undefined)
@@ -120,17 +132,20 @@ let GpxDisplayService = (() => {
120
132
  return { ...position, heading: getHeading(this.getOriginalRoute(), position) };
121
133
  }
122
134
  catch (err) {
123
- this.logError(err, 'getInitialStreetViewPosition');
135
+ this.logError(err, logContext);
124
136
  return position;
125
137
  }
126
138
  }
127
139
  waitsForStreetView() {
128
140
  return this.isMobile() && this.getRideSettingsDisplay().getRideView() === 'sv';
129
141
  }
142
+ waitsForSatelliteView() {
143
+ return this.isMobile() && this.getRideSettingsDisplay().getRideView() === 'sat';
144
+ }
130
145
  getSatelliteViewProps() {
131
146
  return {
132
147
  onDisplayEvent: this.onSatelliteViewEvent.bind(this),
133
- displayPosition: this.position
148
+ displayPosition: this.getSatelliteViewPosition()
134
149
  };
135
150
  }
136
151
  getMapViewProps() {
@@ -142,7 +157,7 @@ let GpxDisplayService = (() => {
142
157
  }
143
158
  getStartOverlayProps() {
144
159
  const rideView = this.getRideSettingsDisplay().getRideView();
145
- if (rideView === 'map' || (this.isMobile() && !this.waitsForStreetView())) {
160
+ if (rideView === 'map' || (this.isMobile() && !this.waitsForStreetView() && !this.waitsForSatelliteView())) {
146
161
  return {
147
162
  mapType: this.getRideViewName(),
148
163
  mapState: 'Loaded'
@@ -156,11 +171,11 @@ let GpxDisplayService = (() => {
156
171
  }
157
172
  isStartRideCompleted() {
158
173
  const rideView = this.getRideSettingsDisplay().getRideView();
159
- if (rideView === 'map' || (this.isMobile() && !this.waitsForStreetView())) {
174
+ if (rideView === 'map' || (this.isMobile() && !this.waitsForStreetView() && !this.waitsForSatelliteView())) {
160
175
  this.mapLoaded = true;
161
176
  return true;
162
177
  }
163
- if (this.svStartTimedOut)
178
+ if (this.svStartTimedOut || this.satStartTimedOut)
164
179
  return true;
165
180
  return this.mapLoaded;
166
181
  }
@@ -196,6 +211,7 @@ let GpxDisplayService = (() => {
196
211
  onSatelliteViewEvent(state, error) {
197
212
  if (state === 'Loaded') {
198
213
  this.mapLoaded = true;
214
+ this.clearSatelliteViewStartTimeout();
199
215
  }
200
216
  else if (state === 'Error') {
201
217
  this.logEvent({ message: 'sat view error', error: this.mapError });
@@ -285,12 +301,35 @@ let GpxDisplayService = (() => {
285
301
  getStreetViewStartTimeout() {
286
302
  return this.getNumSetting('SV_START_TIMEOUT') ?? SV_START_TIMEOUT;
287
303
  }
304
+ armSatelliteViewStartTimeout() {
305
+ this.clearSatelliteViewStartTimeout();
306
+ const timeout = this.getSatelliteViewStartTimeout();
307
+ this.satStartTimeout = setTimeout(() => {
308
+ this.satStartTimeout = undefined;
309
+ if (this.mapLoaded)
310
+ return;
311
+ this.satStartTimedOut = true;
312
+ this.logEvent({ message: 'satellite view start timeout', timeout });
313
+ this.emit('state-update');
314
+ }, timeout);
315
+ }
316
+ clearSatelliteViewStartTimeout() {
317
+ if (this.satStartTimeout) {
318
+ clearTimeout(this.satStartTimeout);
319
+ this.satStartTimeout = undefined;
320
+ }
321
+ }
322
+ getSatelliteViewStartTimeout() {
323
+ return this.getNumSetting('SAT_START_TIMEOUT') ?? SAT_START_TIMEOUT;
324
+ }
288
325
  onStarted() {
289
326
  this.clearStreetViewStartTimeout();
327
+ this.clearSatelliteViewStartTimeout();
290
328
  super.onStarted();
291
329
  }
292
330
  async stop() {
293
331
  this.clearStreetViewStartTimeout();
332
+ this.clearSatelliteViewStartTimeout();
294
333
  return super.stop();
295
334
  }
296
335
  getStreetViewObserver() {
@@ -413,6 +413,8 @@ let RouteCard = (() => {
413
413
  }
414
414
  updateStartPos(p, data) {
415
415
  const [C, U] = getUnitConversionShortcuts();
416
+ if (p === undefined || p === null)
417
+ return null;
416
418
  let value;
417
419
  if (typeof p === 'number')
418
420
  value = p;
@@ -37,6 +37,10 @@ import { Injectable, Singleton } from "../../../base/decorators";
37
37
  import { IncyclistService } from "../../../base/service";
38
38
  import { Observer } from "../../../base/types";
39
39
  import { useUserSettings } from "../../service";
40
+ const UNAVAILABLE_MESSAGES = {
41
+ 'need.playservices': 'Install Google Play Services to use this view',
42
+ };
43
+ const DEFAULT_UNAVAILABLE_MESSAGE = 'This view is currently unavailable on your device';
40
44
  let RideSettingsDisplayService = (() => {
41
45
  let _classDecorators = [Singleton];
42
46
  let _classDescriptor;
@@ -80,8 +84,6 @@ let RideSettingsDisplayService = (() => {
80
84
  };
81
85
  }
82
86
  setRideView(rideView) {
83
- if (this.isRestricted())
84
- return;
85
87
  try {
86
88
  this.getUserSettings().set('preferences.rideView', rideView);
87
89
  }
@@ -94,29 +96,29 @@ let RideSettingsDisplayService = (() => {
94
96
  this.observer.emit('changed', this.getDisplayProps());
95
97
  }
96
98
  getRideView() {
97
- if (this.isRestricted())
98
- return 'map';
99
99
  const rideView = this.getUserSettings().get('preferences.rideView', 'sv');
100
+ const availability = this.getBindings().mapAvailability?.isAvailable(rideView);
101
+ if (availability?.status === 'unavailable' || availability?.status === 'not-supported')
102
+ return 'map';
100
103
  return rideView;
101
104
  }
102
105
  getRideViewOptions() {
103
106
  const map = new Map();
104
- if (this.isRestricted()) {
105
- map.set('map', 'Map');
106
- return map;
107
- }
108
- map.set('sv', 'Street View');
109
- map.set('map', 'Map');
110
- if (!this.isMobile())
111
- map.set('sat', 'Satellite View');
107
+ this.addRideViewOption(map, 'sv', 'Street View');
108
+ map.set('map', { label: 'Map' });
109
+ this.addRideViewOption(map, 'sat', 'Satellite View');
112
110
  return map;
113
111
  }
114
- isRestricted() {
115
- if (this.isMobile()) {
116
- const secretsStatus = this.getSecretBinding()?.getSecretsStatus?.();
117
- return (secretsStatus === 'stale' || secretsStatus === 'missing' || secretsStatus === undefined);
112
+ addRideViewOption(map, key, label) {
113
+ const availability = this.getBindings().mapAvailability?.isAvailable(key);
114
+ if (availability?.status === 'not-supported')
115
+ return;
116
+ if (availability?.status === 'unavailable') {
117
+ const message = UNAVAILABLE_MESSAGES[availability.messageKey ?? ''] ?? DEFAULT_UNAVAILABLE_MESSAGE;
118
+ map.set(key, { label, disabled: true, message });
119
+ return;
118
120
  }
119
- return false;
121
+ map.set(key, { label });
120
122
  }
121
123
  isMobile() {
122
124
  return this.getBindings().appInfo?.getChannel() === 'mobile';
@@ -133,9 +135,6 @@ let RideSettingsDisplayService = (() => {
133
135
  getBindings() {
134
136
  return getBindings();
135
137
  }
136
- getSecretBinding() {
137
- return this.getBindings().secret;
138
- }
139
138
  };
140
139
  return RideSettingsDisplayService = _classThis;
141
140
  })();
@@ -12,6 +12,7 @@ import type { ISecretBinding } from '../secret';
12
12
  import type { ISerialBinding } from '../serial/types';
13
13
  import type { ICryptoBinding } from '../crypto/types';
14
14
  import type { IFetchBinding } from '../fetch/types';
15
+ import type { IMapAvailabilityBinding } from '../mapAvailability/types';
15
16
  export interface IUserSettingsBinding {
16
17
  getAll(): Promise<any>;
17
18
  set(key: string, value: any): Promise<boolean>;
@@ -28,6 +29,7 @@ export declare class IncyclistBindings {
28
29
  downloadManager?: IDownloadManager;
29
30
  form?: IFormPostBinding;
30
31
  secret?: ISecretBinding;
32
+ mapAvailability?: IMapAvailabilityBinding;
31
33
  mq: IMessageQueueBinding;
32
34
  ui: INativeUI;
33
35
  settings: IUserSettingsBinding;
@@ -0,0 +1,10 @@
1
+ import type { TRideView } from '../../settings/display/ride/types';
2
+ export type AvailabilityStatus = 'available' | 'unavailable' | 'not-supported';
3
+ export interface AvailabilityResult {
4
+ status: AvailabilityStatus;
5
+ messageKey?: string;
6
+ }
7
+ export interface IMapAvailabilityBinding {
8
+ isAvailable(key: TRideView): AvailabilityResult;
9
+ onChange(cb: (key: TRideView, result: AvailabilityResult) => void): void;
10
+ }
@@ -2,7 +2,7 @@ import { GoogleMapsService } from "../../apps";
2
2
  import { Observer } from "../../base/types";
3
3
  import { Route } from "../../routes/base/model/route";
4
4
  import { RoutePoint } from "../../types";
5
- import { CurrentRideDisplayProps, GpxDisplayProps } from "../base";
5
+ import { CurrentPosition, CurrentRideDisplayProps, GpxDisplayProps } from "../base";
6
6
  import { RouteDisplayService } from "./RouteDisplayService";
7
7
  import { SatelliteViewEvent, StreetViewEvent } from "./types";
8
8
  export declare class GpxDisplayService extends RouteDisplayService {
@@ -23,19 +23,24 @@ export declare class GpxDisplayService extends RouteDisplayService {
23
23
  protected updateDurations: Array<number>;
24
24
  protected svStartTimedOut: boolean;
25
25
  protected svStartTimeout: NodeJS.Timeout;
26
+ protected satStartTimedOut: boolean;
27
+ protected satStartTimeout: NodeJS.Timeout;
26
28
  constructor();
27
29
  protected initView(): void;
28
30
  getStreetViewProps(rideProps: CurrentRideDisplayProps): any;
29
- protected getInitialStreetViewPosition(): import("../base").CurrentPosition;
31
+ protected getInitialStreetViewPosition(): CurrentPosition;
32
+ protected getSatelliteViewPosition(): CurrentPosition;
33
+ protected enrichWithHeading(position: CurrentPosition | undefined, logContext: string): CurrentPosition;
30
34
  protected waitsForStreetView(): boolean;
35
+ protected waitsForSatelliteView(): boolean;
31
36
  getSatelliteViewProps(): {
32
37
  onDisplayEvent: any;
33
- displayPosition: import("../base").CurrentPosition;
38
+ displayPosition: CurrentPosition;
34
39
  };
35
40
  getMapViewProps(): {
36
41
  onDisplayEvent: any;
37
42
  showMap: boolean;
38
- displayPosition: import("../base").CurrentPosition;
43
+ displayPosition: CurrentPosition;
39
44
  };
40
45
  getStartOverlayProps(): {
41
46
  mapType: string;
@@ -57,6 +62,9 @@ export declare class GpxDisplayService extends RouteDisplayService {
57
62
  protected armStreetViewStartTimeout(): void;
58
63
  protected clearStreetViewStartTimeout(): void;
59
64
  protected getStreetViewStartTimeout(): number;
65
+ protected armSatelliteViewStartTimeout(): void;
66
+ protected clearSatelliteViewStartTimeout(): void;
67
+ protected getSatelliteViewStartTimeout(): number;
60
68
  onStarted(): void;
61
69
  stop(): Promise<void>;
62
70
  protected getStreetViewObserver(): Observer;
@@ -1,9 +1,8 @@
1
- import { ISecretBinding } from "../../../api";
2
1
  import { IncyclistService } from "../../../base/service";
3
2
  import { Observer } from "../../../base/types";
4
3
  import { IObserver } from "../../../types";
5
4
  import { UserSettingsService } from "../../service";
6
- import { RideSettingsDisplayProps, TRideView } from "./types";
5
+ import { RideSettingsDisplayProps, TRideView, TRideViewOption } from "./types";
7
6
  export declare class RideSettingsDisplayService extends IncyclistService {
8
7
  protected observer: Observer;
9
8
  constructor();
@@ -13,13 +12,12 @@ export declare class RideSettingsDisplayService extends IncyclistService {
13
12
  setRideView(rideView: TRideView): void;
14
13
  protected emitChanged(): void;
15
14
  getRideView(): TRideView;
16
- getRideViewOptions(): Map<TRideView, string>;
17
- protected isRestricted(): boolean;
15
+ getRideViewOptions(): Map<TRideView, TRideViewOption>;
16
+ protected addRideViewOption(map: Map<TRideView, TRideViewOption>, key: TRideView, label: string): void;
18
17
  protected isMobile(): boolean;
19
18
  protected isAndroid(): boolean;
20
19
  protected isIOS(): boolean;
21
20
  protected getUserSettings(): UserSettingsService;
22
21
  protected getBindings(): import("../../../api").IncyclistBindings;
23
- protected getSecretBinding(): ISecretBinding | undefined;
24
22
  }
25
23
  export declare const useRideSettingsDisplay: () => RideSettingsDisplayService;
@@ -1,5 +1,10 @@
1
1
  export type TRideView = 'sv' | 'sat' | 'map';
2
+ export interface TRideViewOption {
3
+ label: string;
4
+ disabled?: boolean;
5
+ message?: string;
6
+ }
2
7
  export interface RideSettingsDisplayProps {
3
8
  rideView: TRideView;
4
- rideViewOptions: Map<TRideView, string>;
9
+ rideViewOptions: Map<TRideView, TRideViewOption>;
5
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-services",
3
- "version": "1.7.121",
3
+ "version": "1.7.125",
4
4
  "peerDependencies": {
5
5
  "gd-eventlog": "^0.1.27"
6
6
  },