1import { 2 DebugControlService 3} from "./chunk-PFRFKH6U.js"; 4import { 5 BeaconService 6} from "./chunk-UZKEIBGO.js"; 7import "./chunk-2E4THSOE.js"; 8import "./chunk-JISY7VJD.js"; 9import "./chunk-KP4RHBP7.js"; 10import { 11 DeviceDetectionService, 12 SettingsService 13} from "./chunk-QI7JV4VS.js"; 14import "./chunk-OTQ6GTAJ.js"; 15import { 16 AlertController, 17 IonButton, 18 IonButtons, 19 IonCard, 20 IonCardContent, 21 IonCardHeader, 22 IonCardTitle, 23 IonChip, 24 IonContent, 25 IonFab, 26 IonFabButton, 27 IonHeader, 28 IonInput, 29 IonMenuButton, 30 IonSelect, 31 IonSelectOption, 32 IonTitle, 33 IonToggle, 34 IonToolbar 35} from "./chunk-RLZ522BW.js"; 36import { 37 DatabaseService 38} from "./chunk-RLJCY5HS.js"; 39import { 40 LanguageService 41} from "./chunk-SJZLX5SX.js"; 42import { 43 ToastService 44} from "./chunk-GR5DEE5Y.js"; 45import { 46 TranslateModule, 47 TranslatePipe, 48 TranslateService 49} from "./chunk-O5XYYQCR.js"; 50import { 51 AuthService, 52 UserRole 53} from "./chunk-QGEJYSW7.js"; 54import { 55 ApiUrlService 56} from "./chunk-MAIAEXGG.js"; 57import { 58 environment 59} from "./chunk-L4O6SE3A.js"; 60import "./chunk-INK5THDW.js"; 61import { 62 NgIcon, 63 lucideActivity, 64 lucideArrowUpDown, 65 lucideBell, 66 lucideBluetooth, 67 lucideBrain, 68 lucideBug, 69 lucideBuilding2, 70 lucideChartLine, 71 lucideChevronDown, 72 lucideChevronUp, 73 lucideCircle, 74 lucideCircleDot, 75 lucideClock, 76 lucideCpu, 77 lucideDownload, 78 lucideDroplets, 79 lucideEye, 80 lucideFile, 81 lucideFileText, 82 lucideFilter, 83 lucideGauge, 84 lucideGitBranchPlus, 85 lucideGlobe, 86 lucideGrid3x3, 87 lucideHand, 88 lucideHistory, 89 lucideInfo, 90 lucideLayers, 91 lucideLock, 92 lucideMagnet, 93 lucideMapPin, 94 lucideMenu, 95 lucideMonitor, 96 lucideMousePointer, 97 lucideMove, 98 lucideMoveHorizontal, 99 lucideNavigation, 100 lucideNavigation2, 101 lucideOctagon, 102 lucidePaintbrush, 103 lucidePalette, 104 lucidePlay, 105 lucideRadar, 106 lucideRadio, 107 lucideRainbow, 108 lucideRefreshCw, 109 lucideRotateCw, 110 lucideRoute, 111 lucideRuler, 112 lucideSatellite, 113 lucideSave, 114 lucideSettings, 115 lucideSettings2, 116 lucideShare, 117 lucideSignalHigh, 118 lucideSignalLow, 119 lucideSlidersHorizontal, 120 lucideSmartphone, 121 lucideSparkles, 122 lucideSquare, 123 lucideSun, 124 lucideTag, 125 lucideTarget, 126 lucideTimer, 127 lucideTimerOff, 128 lucideToggleLeft, 129 lucideTrash2, 130 lucideTrendingDown, 131 lucideTrendingUp, 132 lucideTriangleAlert, 133 lucideUsers, 134 lucideVolume2, 135 lucideWaves, 136 lucideZap, 137 provideIcons 138} from "./chunk-GMPIA5L4.js"; 139import { 140 Component, 141 FormBuilder, 142 FormControlName, 143 FormGroupDirective, 144 FormsModule, 145 NgControlStatus, 146 NgControlStatusGroup, 147 NgModel, 148 ReactiveFormsModule, 149 Validators, 150 setClassMetadata, 151 take, 152 ɵNgNoValidate, 153 ɵsetClassDebugInfo, 154 ɵɵProvidersFeature, 155 ɵɵadvance, 156 ɵɵconditional, 157 ɵɵdefineComponent, 158 ɵɵdirectiveInject, 159 ɵɵelement, 160 ɵɵelementEnd, 161 ɵɵelementStart, 162 ɵɵgetCurrentView, 163 ɵɵlistener, 164 ɵɵnextContext, 165 ɵɵpipe, 166 ɵɵpipeBind1, 167 ɵɵproperty, 168 ɵɵpureFunction0, 169 ɵɵrepeater, 170 ɵɵrepeaterCreate, 171 ɵɵresetView, 172 ɵɵrestoreView, 173 ɵɵtemplate, 174 ɵɵtext, 175 ɵɵtextInterpolate, 176 ɵɵtextInterpolate1, 177 ɵɵtextInterpolate2, 178 ɵɵtextInterpolate4, 179 ɵɵtwoWayBindingSet, 180 ɵɵtwoWayListener, 181 ɵɵtwoWayProperty 182} from "./chunk-UQ6LLOJ6.js"; 183import "./chunk-BD3NMR2S.js"; 184import "./chunk-6HPUB4U6.js"; 185import "./chunk-JTG2GCS6.js"; 186import "./chunk-WGFJL45C.js"; 187import "./chunk-7WVISTDL.js"; 188import "./chunk-2S57T3GS.js"; 189import "./chunk-R4QHACMO.js"; 190import "./chunk-4MEJEBWM.js"; 191import "./chunk-RIBVNXHQ.js"; 192import "./chunk-Z42OVMMO.js"; 193import "./chunk-O5S42IXR.js"; 194import "./chunk-QBR2RTFG.js"; 195import "./chunk-MIOLVGSM.js"; 196import "./chunk-V3YFOG6Q.js"; 197import "./chunk-LPMBLWVS.js"; 198import "./chunk-5LKHIIQE.js"; 199import "./chunk-ITE2OHLM.js"; 200import "./chunk-C46CB72A.js"; 201import "./chunk-SRPSML5O.js"; 202import "./chunk-NRSVX4KN.js"; 203import "./chunk-T4GYAOTA.js"; 204import "./chunk-2VHYZHLL.js"; 205import "./chunk-S6LHOZ5A.js"; 206import "./chunk-Y6HZOH3Q.js"; 207import "./chunk-TWQHADEW.js"; 208import "./chunk-3J4L7S6G.js"; 209import "./chunk-IL42VKT6.js"; 210import "./chunk-LONO5O5R.js"; 211import "./chunk-KFBF5L4X.js"; 212import "./chunk-PWC4K6CW.js"; 213import "./chunk-R6JLIESI.js"; 214import "./chunk-UG6K57PI.js"; 215import "./chunk-UR6VIRNL.js"; 216import "./chunk-OJO5RD3M.js"; 217import { 218 __async, 219 __objRest, 220 __spreadValues 221} from "./chunk-CO64IJQE.js"; 222
223// src/app/pages/settings/settings.page.ts 224var _c0 = () => ({ standalone: true }); 225var _forTrack0 = ($index, $item) => $item.url; 226var _forTrack1 = ($index, $item) => $item.id; 227function SettingsPage_Conditional_80_Template(rf, ctx) { 228 if (rf & 1) { 229 \u0275\u0275elementStart(0, "div", 29)(1, "span"); 230 \u0275\u0275text(2); 231 \u0275\u0275pipe(3, "translate"); 232 \u0275\u0275elementEnd()(); 233 } 234 if (rf & 2) { 235 \u0275\u0275advance(2); 236 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(3, 1, "settings.display.title")); 237 } 238} 239function SettingsPage_Conditional_194_Conditional_24_Template(rf, ctx) { 240 if (rf & 1) { 241 \u0275\u0275elementStart(0, "div", 10)(1, "div", 11)(2, "div", 12); 242 \u0275\u0275element(3, "ng-icon", 62); 243 \u0275\u0275elementEnd(); 244 \u0275\u0275elementStart(4, "div", 14)(5, "h4"); 245 \u0275\u0275text(6); 246 \u0275\u0275pipe(7, "translate"); 247 \u0275\u0275elementEnd(); 248 \u0275\u0275elementStart(8, "p"); 249 \u0275\u0275text(9); 250 \u0275\u0275pipe(10, "translate"); 251 \u0275\u0275elementEnd()()(); 252 \u0275\u0275element(11, "ion-input", 63); 253 \u0275\u0275elementEnd(); 254 } 255 if (rf & 2) { 256 \u0275\u0275advance(6); 257 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(7, 2, "settings.segment_hysteresis_threshold")); 258 \u0275\u0275advance(3); 259 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(10, 4, "settings.segment_hysteresis_threshold_desc")); 260 } 261} 262function SettingsPage_Conditional_194_Template(rf, ctx) { 263 if (rf & 1) { 264 \u0275\u0275elementStart(0, "div", 24)(1, "div", 11)(2, "div", 12); 265 \u0275\u0275element(3, "ng-icon", 54); 266 \u0275\u0275elementEnd(); 267 \u0275\u0275elementStart(4, "div", 14)(5, "h4"); 268 \u0275\u0275text(6); 269 \u0275\u0275pipe(7, "translate"); 270 \u0275\u0275elementEnd(); 271 \u0275\u0275elementStart(8, "p"); 272 \u0275\u0275text(9); 273 \u0275\u0275pipe(10, "translate"); 274 \u0275\u0275elementEnd()()(); 275 \u0275\u0275element(11, "ion-toggle", 55); 276 \u0275\u0275elementEnd(); 277 \u0275\u0275elementStart(12, "div", 24)(13, "div", 11)(14, "div", 12); 278 \u0275\u0275element(15, "ng-icon", 56); 279 \u0275\u0275elementEnd(); 280 \u0275\u0275elementStart(16, "div", 14)(17, "h4"); 281 \u0275\u0275text(18); 282 \u0275\u0275pipe(19, "translate"); 283 \u0275\u0275elementEnd(); 284 \u0275\u0275elementStart(20, "p"); 285 \u0275\u0275text(21); 286 \u0275\u0275pipe(22, "translate"); 287 \u0275\u0275elementEnd()()(); 288 \u0275\u0275element(23, "ion-toggle", 57); 289 \u0275\u0275elementEnd(); 290 \u0275\u0275template(24, SettingsPage_Conditional_194_Conditional_24_Template, 12, 6, "div", 10); 291 \u0275\u0275elementStart(25, "div", 24)(26, "div", 11)(27, "div", 12); 292 \u0275\u0275element(28, "ng-icon", 58); 293 \u0275\u0275elementEnd(); 294 \u0275\u0275elementStart(29, "div", 14)(30, "h4"); 295 \u0275\u0275text(31); 296 \u0275\u0275pipe(32, "translate"); 297 \u0275\u0275elementEnd(); 298 \u0275\u0275elementStart(33, "p"); 299 \u0275\u0275text(34); 300 \u0275\u0275pipe(35, "translate"); 301 \u0275\u0275elementEnd()()(); 302 \u0275\u0275element(36, "ion-toggle", 59); 303 \u0275\u0275elementEnd(); 304 \u0275\u0275elementStart(37, "div", 24)(38, "div", 11)(39, "div", 12); 305 \u0275\u0275element(40, "ng-icon", 60); 306 \u0275\u0275elementEnd(); 307 \u0275\u0275elementStart(41, "div", 14)(42, "h4"); 308 \u0275\u0275text(43); 309 \u0275\u0275pipe(44, "translate"); 310 \u0275\u0275elementEnd(); 311 \u0275\u0275elementStart(45, "p"); 312 \u0275\u0275text(46); 313 \u0275\u0275pipe(47, "translate"); 314 \u0275\u0275elementEnd()()(); 315 \u0275\u0275element(48, "ion-toggle", 61); 316 \u0275\u0275elementEnd(); 317 } 318 if (rf & 2) { 319 let tmp_5_0; 320 const ctx_r0 = \u0275\u0275nextContext(); 321 \u0275\u0275advance(6); 322 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(7, 9, "settings.navigationSection.smartSourceSwitching.title")); 323 \u0275\u0275advance(3); 324 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(10, 11, "settings.navigationSection.smartSourceSwitching.description")); 325 \u0275\u0275advance(9); 326 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(19, 13, "settings.enable_segment_hysteresis")); 327 \u0275\u0275advance(3); 328 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(22, 15, "settings.enable_segment_hysteresis_desc")); 329 \u0275\u0275advance(3); 330 \u0275\u0275conditional(((tmp_5_0 = ctx_r0.settingsForm.get("enableSegmentHysteresis")) == null ? null : tmp_5_0.value) ? 24 : -1); 331 \u0275\u0275advance(7); 332 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(32, 17, "settings.navigationSection.forceDualMode.title")); 333 \u0275\u0275advance(3); 334 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(35, 19, "settings.navigationSection.forceDualMode.description")); 335 \u0275\u0275advance(9); 336 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(44, 21, "settings.navigationSection.forceBeaconOnly.title")); 337 \u0275\u0275advance(3); 338 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(47, 23, "settings.navigationSection.forceBeaconOnly.description")); 339 } 340} 341function SettingsPage_Conditional_195_Conditional_38_Template(rf, ctx) { 342 if (rf & 1) { 343 \u0275\u0275elementStart(0, "div", 73)(1, "div", 10)(2, "div", 11)(3, "div", 12); 344 \u0275\u0275element(4, "ng-icon", 46); 345 \u0275\u0275elementEnd(); 346 \u0275\u0275elementStart(5, "div", 14)(6, "h4"); 347 \u0275\u0275text(7); 348 \u0275\u0275pipe(8, "translate"); 349 \u0275\u0275elementEnd(); 350 \u0275\u0275elementStart(9, "p"); 351 \u0275\u0275text(10); 352 \u0275\u0275pipe(11, "translate"); 353 \u0275\u0275elementEnd()()(); 354 \u0275\u0275element(12, "ion-input", 76); 355 \u0275\u0275elementEnd(); 356 \u0275\u0275elementStart(13, "div", 10)(14, "div", 11)(15, "div", 12); 357 \u0275\u0275element(16, "ng-icon", 77); 358 \u0275\u0275elementEnd(); 359 \u0275\u0275elementStart(17, "div", 14)(18, "h4"); 360 \u0275\u0275text(19); 361 \u0275\u0275pipe(20, "translate"); 362 \u0275\u0275elementEnd(); 363 \u0275\u0275elementStart(21, "p"); 364 \u0275\u0275text(22); 365 \u0275\u0275pipe(23, "translate"); 366 \u0275\u0275elementEnd()()(); 367 \u0275\u0275element(24, "ion-input", 78); 368 \u0275\u0275elementEnd(); 369 \u0275\u0275elementStart(25, "div", 10)(26, "div", 11)(27, "div", 12); 370 \u0275\u0275element(28, "ng-icon", 54); 371 \u0275\u0275elementEnd(); 372 \u0275\u0275elementStart(29, "div", 14)(30, "h4"); 373 \u0275\u0275text(31); 374 \u0275\u0275pipe(32, "translate"); 375 \u0275\u0275elementEnd(); 376 \u0275\u0275elementStart(33, "p"); 377 \u0275\u0275text(34); 378 \u0275\u0275pipe(35, "translate"); 379 \u0275\u0275elementEnd()()(); 380 \u0275\u0275element(36, "ion-input", 79); 381 \u0275\u0275elementEnd()(); 382 } 383 if (rf & 2) { 384 \u0275\u0275advance(7); 385 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(8, 6, "settings.rssiFilter.kalman.processNoise.title")); 386 \u0275\u0275advance(3); 387 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(11, 8, "settings.rssiFilter.kalman.processNoise.description")); 388 \u0275\u0275advance(9); 389 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(20, 10, "settings.rssiFilter.kalman.measurementNoise.title")); 390 \u0275\u0275advance(3); 391 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(23, 12, "settings.rssiFilter.kalman.measurementNoise.description")); 392 \u0275\u0275advance(9); 393 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(32, 14, "settings.rssiFilter.kalman.estimationError.title")); 394 \u0275\u0275advance(3); 395 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(35, 16, "settings.rssiFilter.kalman.estimationError.description")); 396 } 397} 398function SettingsPage_Conditional_195_Conditional_39_Template(rf, ctx) { 399 if (rf & 1) { 400 \u0275\u0275elementStart(0, "div", 73)(1, "div", 10)(2, "div", 11)(3, "div", 12); 401 \u0275\u0275element(4, "ng-icon", 80); 402 \u0275\u0275elementEnd(); 403 \u0275\u0275elementStart(5, "div", 14)(6, "h4"); 404 \u0275\u0275text(7); 405 \u0275\u0275pipe(8, "translate"); 406 \u0275\u0275elementEnd(); 407 \u0275\u0275elementStart(9, "p"); 408 \u0275\u0275text(10); 409 \u0275\u0275pipe(11, "translate"); 410 \u0275\u0275elementEnd()()(); 411 \u0275\u0275element(12, "ion-input", 81); 412 \u0275\u0275elementEnd(); 413 \u0275\u0275elementStart(13, "div", 10)(14, "div", 11)(15, "div", 12); 414 \u0275\u0275element(16, "ng-icon", 82); 415 \u0275\u0275elementEnd(); 416 \u0275\u0275elementStart(17, "div", 14)(18, "h4"); 417 \u0275\u0275text(19); 418 \u0275\u0275pipe(20, "translate"); 419 \u0275\u0275elementEnd(); 420 \u0275\u0275elementStart(21, "p"); 421 \u0275\u0275text(22); 422 \u0275\u0275pipe(23, "translate"); 423 \u0275\u0275elementEnd()()(); 424 \u0275\u0275element(24, "ion-input", 83); 425 \u0275\u0275elementEnd()(); 426 } 427 if (rf & 2) { 428 \u0275\u0275advance(7); 429 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(8, 4, "settings.rssiFilter.ema.baseAlpha.title")); 430 \u0275\u0275advance(3); 431 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(11, 6, "settings.rssiFilter.ema.baseAlpha.description")); 432 \u0275\u0275advance(9); 433 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(20, 8, "settings.rssiFilter.ema.outlierThreshold.title")); 434 \u0275\u0275advance(3); 435 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(23, 10, "settings.rssiFilter.ema.outlierThreshold.description")); 436 } 437} 438function SettingsPage_Conditional_195_Conditional_40_Template(rf, ctx) { 439 if (rf & 1) { 440 \u0275\u0275elementStart(0, "div", 73)(1, "div", 10)(2, "div", 11)(3, "div", 12); 441 \u0275\u0275element(4, "ng-icon", 80); 442 \u0275\u0275elementEnd(); 443 \u0275\u0275elementStart(5, "div", 14)(6, "h4"); 444 \u0275\u0275text(7); 445 \u0275\u0275pipe(8, "translate"); 446 \u0275\u0275elementEnd(); 447 \u0275\u0275elementStart(9, "p"); 448 \u0275\u0275text(10); 449 \u0275\u0275pipe(11, "translate"); 450 \u0275\u0275elementEnd()()(); 451 \u0275\u0275element(12, "ion-input", 84); 452 \u0275\u0275elementEnd(); 453 \u0275\u0275elementStart(13, "div", 10)(14, "div", 11)(15, "div", 12); 454 \u0275\u0275element(16, "ng-icon", 82); 455 \u0275\u0275elementEnd(); 456 \u0275\u0275elementStart(17, "div", 14)(18, "h4"); 457 \u0275\u0275text(19); 458 \u0275\u0275pipe(20, "translate"); 459 \u0275\u0275elementEnd(); 460 \u0275\u0275elementStart(21, "p"); 461 \u0275\u0275text(22); 462 \u0275\u0275pipe(23, "translate"); 463 \u0275\u0275elementEnd()()(); 464 \u0275\u0275element(24, "ion-input", 85); 465 \u0275\u0275elementEnd()(); 466 } 467 if (rf & 2) { 468 \u0275\u0275advance(7); 469 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(8, 4, "settings.rssiFilter.ema.alpha.title")); 470 \u0275\u0275advance(3); 471 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(11, 6, "settings.rssiFilter.ema.alpha.description")); 472 \u0275\u0275advance(9); 473 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(20, 8, "settings.rssiFilter.ema.outlierThreshold.title")); 474 \u0275\u0275advance(3); 475 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(23, 10, "settings.rssiFilter.ema.outlierThreshold.description")); 476 } 477} 478function SettingsPage_Conditional_195_Conditional_57_Template(rf, ctx) { 479 if (rf & 1) { 480 \u0275\u0275elementStart(0, "div", 10)(1, "div", 11)(2, "div", 12); 481 \u0275\u0275element(3, "ng-icon", 86); 482 \u0275\u0275elementEnd(); 483 \u0275\u0275elementStart(4, "div", 14)(5, "h4"); 484 \u0275\u0275text(6); 485 \u0275\u0275pipe(7, "translate"); 486 \u0275\u0275elementEnd(); 487 \u0275\u0275elementStart(8, "p"); 488 \u0275\u0275text(9); 489 \u0275\u0275pipe(10, "translate"); 490 \u0275\u0275elementEnd()()(); 491 \u0275\u0275element(11, "ion-input", 87); 492 \u0275\u0275elementEnd(); 493 \u0275\u0275elementStart(12, "div", 10)(13, "div", 11)(14, "div", 12); 494 \u0275\u0275element(15, "ng-icon", 88); 495 \u0275\u0275elementEnd(); 496 \u0275\u0275elementStart(16, "div", 14)(17, "h4"); 497 \u0275\u0275text(18); 498 \u0275\u0275pipe(19, "translate"); 499 \u0275\u0275elementEnd(); 500 \u0275\u0275elementStart(20, "p");
501 \u0275\u0275text(21); 502 \u0275\u0275pipe(22, "translate"); 503 \u0275\u0275elementEnd()()(); 504 \u0275\u0275element(23, "ion-input", 89); 505 \u0275\u0275elementEnd(); 506 \u0275\u0275elementStart(24, "div", 10)(25, "div", 11)(26, "div", 12); 507 \u0275\u0275element(27, "ng-icon", 90); 508 \u0275\u0275elementEnd(); 509 \u0275\u0275elementStart(28, "div", 14)(29, "h4"); 510 \u0275\u0275text(30); 511 \u0275\u0275pipe(31, "translate"); 512 \u0275\u0275elementEnd(); 513 \u0275\u0275elementStart(32, "p"); 514 \u0275\u0275text(33); 515 \u0275\u0275pipe(34, "translate"); 516 \u0275\u0275elementEnd()()(); 517 \u0275\u0275element(35, "ion-input", 91); 518 \u0275\u0275elementEnd(); 519 } 520 if (rf & 2) { 521 \u0275\u0275advance(6); 522 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(7, 6, "settings.positionKalman.maxVelocity.title")); 523 \u0275\u0275advance(3); 524 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(10, 8, "settings.positionKalman.maxVelocity.description")); 525 \u0275\u0275advance(9); 526 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(19, 10, "settings.positionKalman.velocityDecay.title")); 527 \u0275\u0275advance(3); 528 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(22, 12, "settings.positionKalman.velocityDecay.description")); 529 \u0275\u0275advance(9); 530 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(31, 14, "settings.positionKalman.pathSnapDistance.title")); 531 \u0275\u0275advance(3); 532 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(34, 16, "settings.positionKalman.pathSnapDistance.description")); 533 } 534} 535function SettingsPage_Conditional_195_Template(rf, ctx) { 536 if (rf & 1) { 537 \u0275\u0275elementStart(0, "div", 5)(1, "div", 6)(2, "div", 64); 538 \u0275\u0275element(3, "ng-icon", 65); 539 \u0275\u0275elementEnd(); 540 \u0275\u0275elementStart(4, "h3"); 541 \u0275\u0275text(5); 542 \u0275\u0275pipe(6, "translate"); 543 \u0275\u0275elementEnd(); 544 \u0275\u0275elementStart(7, "p"); 545 \u0275\u0275text(8); 546 \u0275\u0275pipe(9, "translate"); 547 \u0275\u0275elementEnd()(); 548 \u0275\u0275elementStart(10, "div", 9)(11, "div", 10)(12, "div", 11)(13, "div", 12); 549 \u0275\u0275element(14, "ng-icon", 66); 550 \u0275\u0275elementEnd(); 551 \u0275\u0275elementStart(15, "div", 14)(16, "h4"); 552 \u0275\u0275text(17); 553 \u0275\u0275pipe(18, "translate"); 554 \u0275\u0275elementEnd(); 555 \u0275\u0275elementStart(19, "p"); 556 \u0275\u0275text(20); 557 \u0275\u0275pipe(21, "translate"); 558 \u0275\u0275elementEnd()()(); 559 \u0275\u0275elementStart(22, "ion-select", 67)(23, "ion-select-option", 68); 560 \u0275\u0275text(24); 561 \u0275\u0275pipe(25, "translate"); 562 \u0275\u0275elementEnd(); 563 \u0275\u0275elementStart(26, "ion-select-option", 69); 564 \u0275\u0275text(27); 565 \u0275\u0275pipe(28, "translate"); 566 \u0275\u0275elementEnd(); 567 \u0275\u0275elementStart(29, "ion-select-option", 70); 568 \u0275\u0275text(30); 569 \u0275\u0275pipe(31, "translate"); 570 \u0275\u0275elementEnd(); 571 \u0275\u0275elementStart(32, "ion-select-option", 71); 572 \u0275\u0275text(33); 573 \u0275\u0275pipe(34, "translate"); 574 \u0275\u0275elementEnd(); 575 \u0275\u0275elementStart(35, "ion-select-option", 72); 576 \u0275\u0275text(36); 577 \u0275\u0275pipe(37, "translate"); 578 \u0275\u0275elementEnd()()(); 579 \u0275\u0275template(38, SettingsPage_Conditional_195_Conditional_38_Template, 37, 18, "div", 73)(39, SettingsPage_Conditional_195_Conditional_39_Template, 25, 12, "div", 73)(40, SettingsPage_Conditional_195_Conditional_40_Template, 25, 12, "div", 73); 580 \u0275\u0275elementStart(41, "div", 29)(42, "span"); 581 \u0275\u0275text(43); 582 \u0275\u0275pipe(44, "translate"); 583 \u0275\u0275elementEnd()(); 584 \u0275\u0275elementStart(45, "div", 24)(46, "div", 11)(47, "div", 12); 585 \u0275\u0275element(48, "ng-icon", 74); 586 \u0275\u0275elementEnd(); 587 \u0275\u0275elementStart(49, "div", 14)(50, "h4"); 588 \u0275\u0275text(51); 589 \u0275\u0275pipe(52, "translate"); 590 \u0275\u0275elementEnd(); 591 \u0275\u0275elementStart(53, "p"); 592 \u0275\u0275text(54); 593 \u0275\u0275pipe(55, "translate"); 594 \u0275\u0275elementEnd()()(); 595 \u0275\u0275element(56, "ion-toggle", 75); 596 \u0275\u0275elementEnd(); 597 \u0275\u0275template(57, SettingsPage_Conditional_195_Conditional_57_Template, 36, 18); 598 \u0275\u0275elementEnd()(); 599 } 600 if (rf & 2) { 601 let tmp_11_0; 602 let tmp_12_0; 603 let tmp_13_0; 604 let tmp_17_0; 605 const ctx_r0 = \u0275\u0275nextContext(); 606 \u0275\u0275advance(5); 607 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(6, 17, "settings.signalProcessing.t
607itle")); 608 \u0275\u0275advance(3); 609 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(9, 19, "settings.signalProcessing.description")); 610 \u0275\u0275advance(9); 611 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(18, 21, "settings.rssiFilter.filterType.title")); 612 \u0275\u0275advance(3); 613 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(21, 23, "settings.rssiFilter.filterType.description")); 614 \u0275\u0275advance(2); 615 \u0275\u0275property("selectedText", ctx_r0.rssiFilterTypeLabel); 616 \u0275\u0275advance(2); 617 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(25, 25, "settings.rssiFilter.options.none")); 618 \u0275\u0275advance(3); 619 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(28, 27, "settings.rssiFilter.options.kalman")); 620 \u0275\u0275advance(3); 621 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(31, 29, "settings.rssiFilter.options.adaptiveEma")); 622 \u0275\u0275advance(3); 623 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(34, 31, "settings.rssiFilter.options.simpleEma")); 624 \u0275\u0275advance(3); 625 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(37, 33, "settings.rssiFilter.options.simpleSma")); 626 \u0275\u0275advance(2); 627 \u0275\u0275conditional(((tmp_11_0 = ctx_r0.settingsForm.get("rssiFilterType")) == null ? null : tmp_11_0.value) === "kalman" ? 38 : -1); 628 \u0275\u0275advance(); 629 \u0275\u0275conditional(((tmp_12_0 = ctx_r0.settingsForm.get("rssiFilterType")) == null ? null : tmp_12_0.value) === "adaptiveEma" ? 39 : -1); 630 \u0275\u0275advance(); 631 \u0275\u0275conditional(((tmp_13_0 = ctx_r0.settingsForm.get("rssiFilterType")) == null ? null : tmp_13_0.value) === "simpleEma" ? 40 : -1); 632 \u0275\u0275advance(3); 633 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(44, 35, "settings.signalProcessing.kalmanFilter")); 634 \u0275\u0275advance(8); 635 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(52, 37, "settings.positionKalman.enable.title")); 636 \u0275\u0275advance(3); 637 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(55, 39, "settings.positionKalman.enable.description")); 638 \u0275\u0275advance(3); 639 \u0275\u0275conditional(((tmp_17_0 = ctx_r0.settingsForm.get("enableGraphKalmanFilter")) == null ? null : tmp_17_0.value) ? 57 : -1); 640 } 641} 642function SettingsPage_Conditional_203_Conditional_10_Conditional_29_Template(rf, ctx) { 643 if (rf & 1) { 644 \u0275\u0275elementStart(0, "div", 98)(1, "ion-chip", 104); 645 \u0275\u0275element(2, "ng-icon", 105); 646 \u0275\u0275elementStart(3, "span"); 647 \u0275\u0275text(4); 648 \u0275\u0275pipe(5, "translate"); 649 \u0275\u0275elementEnd()()(); 650 } 651 if (rf & 2) { 652 \u0275\u0275advance(4); 653 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(5, 1, "settings.performance.deviceInfo.flickeringWarning")); 654 } 655} 656function SettingsPage_Conditional_203_Conditional_10_Conditional_30_Template(rf, ctx) { 657 if (rf & 1) { 658 \u0275\u0275elementStart(0, "div", 99)(1, "ion-chip", 106); 659 \u0275\u0275element(2, "ng-icon", 107); 660 \u0275\u0275elementStart(3, "span"); 661 \u0275\u0275text(4); 662 \u0275\u0275pipe(5, "translate"); 663 \u0275\u0275elementEnd()()(); 664 } 665 if (rf & 2) { 666 \u0275\u0275advance(4); 667 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(5, 1, "settings.performance.deviceInfo.lowEndWarning")); 668 } 669} 670function SettingsPage_Conditional_203_Conditional_10_Conditional_37_Template(rf, ctx) { 671 if (rf & 1) { 672 const _r4 = \u0275\u0275getCurrentView(); 673 \u0275\u0275elementStart(0, "ion-button", 108); 674 \u0275\u0275listener("click", function SettingsPage_Conditional_203_Conditional_10_Conditional_37_Template_ion_button_click_0_listener() { 675 \u0275\u0275restoreView(_r4); 676 const ctx_r0 = \u0275\u0275nextContext(3); 677 return \u0275\u0275resetView(ctx_r0.reportFlickering()); 678 }); 679 \u0275\u0275element(1, "ng-icon", 105); 680 \u0275\u0275elementStart(2, "span"); 681 \u0275\u0275text(3); 682 \u0275\u0275pipe(4, "translate"); 683 \u0275\u0275elementEnd()(); 684 } 685 if (rf & 2) { 686 \u0275\u0275advance(3); 687 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(4, 1, "settings.performance.deviceInfo.reportIssue")); 688 } 689} 690function SettingsPage_Conditional_203_Conditional_10_Template(rf, ctx) { 691 if (rf & 1) { 692 const _r3 = \u0275\u0275getCurrentView(); 693 \u0275\u0275elementStart(0, "ion-card-content")(1, "div", 96)(2, "div", 97)(3, "label"); 694 \u0275\u0275text(4); 695 \u0275\u0275pipe(5, "translate"); 696 \u0275\u0275elementEnd(); 697 \u0275\u0275elementStart(6, "span"); 698 \u0275\u0275text(7); 699 \u0275\u0275pipe(8, "translate"); 700 \u0275\u0275elementEnd()(); 701 \u0275\u0275elementStart(9, "div", 97)(10, "label"); 702 \u0275\u0275text(11); 703 \u0275\u0275pipe(12, "translate"); 704 \u0275\u0275elementEnd(); 705 \u0275\u0275elementStart(13, "span"); 706 \u0275\u0275text(14); 707 \u0275\u0275pipe(15, "translate"); 708 \u0275\u0275elementEnd()(); 709 \u0275\u0275elementStart(16, "div", 97)(17, "label"); 710 \u0275\u0275text(18); 711 \u0275\u0275pipe(19, "translate"); 712 \u0275\u0275elementEnd(); 713 \u0275\u0275elementStart(20, "span");
714 \u0275\u0275text(21); 715 \u0275\u0275pipe(22, "translate"); 716 \u0275\u0275elementEnd()(); 717 \u0275\u0275elementStart(23, "div", 97)(24, "label"); 718 \u0275\u0275text(25); 719 \u0275\u0275pipe(26, "translate"); 720 \u0275\u0275elementEnd(); 721 \u0275\u0275elementStart(27, "span"); 722 \u0275\u0275text(28); 723 \u0275\u0275elementEnd()(); 724 \u0275\u0275template(29, SettingsPage_Conditional_203_Conditional_10_Conditional_29_Template, 6, 3, "div", 98)(30, SettingsPage_Conditional_203_Conditional_10_Conditional_30_Template, 6, 3, "div", 99); 725 \u0275\u0275elementEnd(); 726 \u0275\u0275elementStart(31, "div", 100)(32, "ion-button", 101); 727 \u0275\u0275listener("click", function SettingsPage_Conditional_203_Conditional_10_Template_ion_button_click_32_listener() { 728 \u0275\u0275restoreView(_r3); 729 const ctx_r0 = \u0275\u0275nextContext(2); 730 return \u0275\u0275resetView(ctx_r0.resetDeviceDetection()); 731 }); 732 \u0275\u0275element(33, "ng-icon", 102); 733 \u0275\u0275elementStart(34, "span"); 734 \u0275\u0275text(35); 735 \u0275\u0275pipe(36, "translate"); 736 \u0275\u0275elementEnd()(); 737 \u0275\u0275template(37, SettingsPage_Conditional_203_Conditional_10_Conditional_37_Template, 5, 3, "ion-button", 103); 738 \u0275\u0275elementEnd()(); 739 } 740 if (rf & 2) { 741 const ctx_r0 = \u0275\u0275nextContext(2); 742 \u0275\u0275advance(4); 743 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(5, 12, "settings.performance.deviceInfo.deviceModel")); 744 \u0275\u0275advance(3); 745 \u0275\u0275textInterpolate(ctx_r0.deviceCapabilities.deviceModel || \u0275\u0275pipeBind1(8, 14, "settings.performance.deviceInfo.unknown")); 746 \u0275\u0275advance(4); 747 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(12, 16, "settings.performance.deviceInfo.gpu")); 748 \u0275\u0275advance(3); 749 \u0275\u0275textInterpolate(ctx_r0.deviceCapabilities.gpuRenderer || \u0275\u0275pipeBind1(15, 18, "settings.performance.deviceInfo.unknown")); 750 \u0275\u0275advance(4); 751 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(19, 20, "settings.performance.deviceInfo.webglVersion")); 752 \u0275\u0275advance(3); 753 \u0275\u0275textInterpolate(ctx_r0.deviceCapabilities.webglVersion || \u0275\u0275pipeBind1(22, 22, "settings.performance.deviceInfo.notSupported")); 754 \u0275\u0275advance(4); 755 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(26, 24, "settings.performance.deviceInfo.maxTextureSize")); 756 \u0275\u0275advance(3); 757 \u0275\u0275textInterpolate1("", ctx_r0.deviceCapabilities.maxTextureSize, "px"); 758 \u0275\u0275advance(); 759 \u0275\u0275conditional(ctx_r0.deviceCapabilities.hasKnownFlickeringIssue ? 29 : -1); 760 \u0275\u0275advance(); 761 \u0275\u0275conditional(ctx_r0.deviceCapabilities.isLowEndDevice ? 30 : -1); 762 \u0275\u0275advance(5); 763 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(36, 26, "settings.performance.deviceInfo.redetect")); 764 \u0275\u0275advance(2); 765 \u0275\u0275conditional(ctx_r0.deviceCapabilities.hasKnownFlickeringIssue || ctx_r0.showReportButton ? 37 : -1); 766 } 767} 768function SettingsPage_Conditional_203_Template(rf, ctx) { 769 if (rf & 1) { 770 const _r2 = \u0275\u0275getCurrentView(); 771 \u0275\u0275elementStart(0, "ion-card", 49)(1, "ion-card-header")(2, "ion-card-title")(3, "div", 92); 772 \u0275\u0275element(4, "ng-icon", 93); 773 \u0275\u0275elementStart(5, "span"); 774 \u0275\u0275text(6); 775 \u0275\u0275pipe(7, "translate"); 776 \u0275\u0275elementEnd(); 777 \u0275\u0275elementStart(8, "ion-button", 94); 778 \u0275\u0275listener("click", function SettingsPage_Conditional_203_Template_ion_button_click_8_listener() { 779 \u0275\u0275restoreView(_r2); 780 const ctx_r0 = \u0275\u0275nextContext(); 781 return \u0275\u0275resetView(ctx_r0.toggleDeviceInfo()); 782 }); 783 \u0275\u0275element(9, "ng-icon", 95); 784 \u0275\u0275elementEnd()()()(); 785 \u0275\u0275template(10, SettingsPage_Conditional_203_Conditional_10_Template, 38, 28, "ion-card-content"); 786 \u0275\u0275elementEnd(); 787 } 788 if (rf & 2) { 789 const ctx_r0 = \u0275\u0275nextContext(); 790 \u0275\u0275advance(6); 791 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(7, 3, "settings.performance.deviceInfo.title")); 792 \u0275\u0275advance(3); 793 \u0275\u0275property("name", ctx_r0.showDeviceInfo ? "lucideChevronUp" : "lucideChevronDown"); 794 \u0275\u0275advance(); 795 \u0275\u0275conditional(ctx_r0.showDeviceInfo ? 10 : -1); 796 } 797} 798function SettingsPage_Conditional_204_Conditional_8_Conditional_11_Template(rf, ctx) { 799 if (rf & 1) { 800 \u0275\u0275elementStart(0, "p", 131); 801 \u0275\u0275element(1, "ng-icon", 134); 802 \u0275\u0275text(2); 803 \u0275\u0275pipe(3, "translate"); 804 \u0275\u0275elementEnd(); 805 } 806 if (rf & 2) { 807 \u0275\u0275advance(2); 808 \u0275\u0275textInterpolate1(" ", \u0275\u0275pipeBind1(3, 1, "settings.backend.warning"), " "); 809 } 810} 811function SettingsPage_Conditional_204_Conditional_8_For_14_Template(rf, ctx) { 812 if (rf & 1) { 813 \u0275\u0275elementStart(0, "ion-select-option", 133); 814 \u0275\u0275text(1); 815 \u0275\u0275elementEnd(); 816 } 817 if (rf & 2) { 818 const urlOption_r6 = ctx.$implicit; 819 \u0275\u0275property("value", urlOption_r6.url); 820 \u0275\u0275advance(); 821 \u0275\u0275textInterpolate1(" ", urlOption_r6.name, " "); 822 } 823} 824function SettingsPage_Conditional_204_Conditional_8_Template(rf, ctx) { 825 if (rf & 1) { 826 const _r5 = \u0275\u0275getCurrentView(); 827 \u0275\u0275elementStart(0, "div", 10)(1, "div", 11)(2, "div", 12); 828 \u0275\u0275element(3, "ng-icon", 58); 829 \u0275\u0275elementEnd(); 830 \u0275\u0275elementStart(4, "div", 14)(5, "h4"); 831 \u0275\u0275text(6); 832 \u0275\u0275pipe(7, "translate"); 833 \u0275\u0275elementEnd(); 834 \u0275\u0275elementStart(8, "p"); 835 \u0275\u0275text(9); 836 \u0275\u0275pipe(10, "translate"); 837 \u0275\u0275elementEnd(); 838 \u0275\u0275template(11, SettingsPage_Conditional_204_Conditional_8_Conditional_11_Template, 4, 3, "p", 131); 839 \u0275\u0275elementEnd()(); 840 \u0275\u0275elementStart(12, "ion-select", 132); 841 \u0275\u0275twoWayListener("ngModelChange", function SettingsPage_Conditional_204_Conditional_8_Template_ion_select_ngModelChange_12_listener($event) { 842 \u0275\u0275restoreView(_r5); 843 const ctx_r0 = \u0275\u0275nextContext(2); 844 \u0275\u0275twoWayBindingSet(ctx_r0.selectedApiUrl, $event) || (ctx_r0.selectedApiUrl = $event);
845 return \u0275\u0275resetView($event); 846 }); 847 \u0275\u0275listener("ionChange", function SettingsPage_Conditional_204_Conditional_8_Template_ion_select_ionChange_12_listener() { 848 \u0275\u0275restoreView(_r5); 849 const ctx_r0 = \u0275\u0275nextContext(2); 850 return \u0275\u0275resetView(ctx_r0.onApiUrlChange()); 851 }); 852 \u0275\u0275repeaterCreate(13, SettingsPage_Conditional_204_Conditional_8_For_14_Template, 2, 2, "ion-select-option", 133, _forTrack0); 853 \u0275\u0275elementEnd()(); 854 } 855 if (rf & 2) { 856 const ctx_r0 = \u0275\u0275nextContext(2); 857 \u0275\u0275advance(6); 858 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(7, 6, "settings.backend.server")); 859 \u0275\u0275advance(3); 860 \u0275\u0275textInterpolate2("", \u0275\u0275pipeBind1(10, 8, "settings.backend.current"), ": ", ctx_r0.currentApiUrlName, ""); 861 \u0275\u0275advance(2); 862 \u0275\u0275conditional(ctx_r0.isProduction ? 11 : -1); 863 \u0275\u0275advance(); 864 \u0275\u0275twoWayProperty("ngModel", ctx_r0.selectedApiUrl); 865 \u0275\u0275property("ngModelOptions", \u0275\u0275pureFunction0(10, _c0)); 866 \u0275\u0275advance(); 867 \u0275\u0275repeater(ctx_r0.availableApiUrls); 868 } 869} 870function SettingsPage_Conditional_204_Conditional_58_For_14_Template(rf, ctx) { 871 if (rf & 1) { 872 \u0275\u0275elementStart(0, "ion-select-option", 133); 873 \u0275\u0275text(1); 874 \u0275\u0275elementEnd(); 875 } 876 if (rf & 2) { 877 const preset_r7 = ctx.$implicit; 878 \u0275\u0275property("value", preset_r7.id); 879 \u0275\u0275advance(); 880 \u0275\u0275textInterpolate(preset_r7.name); 881 } 882} 883function SettingsPage_Conditional_204_Conditional_58_Template(rf, ctx) { 884 if (rf & 1) { 885 \u0275\u0275elementStart(0, "div", 121)(1, "div", 11)(2, "div", 12); 886 \u0275\u0275element(3, "ng-icon", 54); 887 \u0275\u0275elementEnd(); 888 \u0275\u0275elementStart(4, "div", 14)(5, "h4"); 889 \u0275\u0275text(6); 890 \u0275\u0275pipe(7, "translate"); 891 \u0275\u0275elementEnd(); 892 \u0275\u0275elementStart(8, "p"); 893 \u0275\u0275text(9); 894 \u0275\u0275pipe(10, "translate"); 895 \u0275\u0275elementEnd()()(); 896 \u0275\u0275elementStart(11, "ion-select", 135); 897 \u0275\u0275pipe(12, "translate"); 898 \u0275\u0275repeaterCreate(13, SettingsPage_Conditional_204_Conditional_58_For_14_Template, 2, 2, "ion-select-option", 133, _forTrack1); 899 \u0275\u0275elementEnd()(); 900 } 901 if (rf & 2) { 902 const ctx_r0 = \u0275\u0275nextContext(2); 903 \u0275\u0275advance(6); 904 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(7, 3, "settings.persistentPosition.preset")); 905 \u0275\u0275advance(3); 906 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(10, 5, "settings.persistentPosition.presetDescription")); 907 \u0275\u0275advance(2); 908 \u0275\u0275property("placeholder", \u0275\u0275pipeBind1(12, 7, "settings.persistentPosition.selectPreset")); 909 \u0275\u0275advance(2); 910 \u0275\u0275repeater(ctx_r0.debugPositionPresets); 911 } 912} 913function SettingsPage_Conditional_204_Conditional_59_Template(rf, ctx) { 914 if (rf & 1) { 915 \u0275\u0275elementStart(0, "div", 122); 916 \u0275\u0275element(1, "ng-icon", 107); 917 \u0275\u0275elementStart(2, "span"); 918 \u0275\u0275text(3); 919 \u0275\u0275pipe(4, "translate"); 920 \u0275\u0275elementEnd()(); 921 } 922 if (rf & 2) { 923 \u0275\u0275advance(3); 924 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(4, 1, "settings.persistentPosition.noPresets")); 925 } 926} 927function SettingsPage_Conditional_204_Conditional_60_Template(rf, ctx) { 928 if (rf & 1) { 929 \u0275\u0275elementStart(0, "div", 123)(1, "strong"); 930 \u0275\u0275text(2); 931 \u0275\u0275elementEnd(); 932 \u0275\u0275elementStart(3, "span"); 933 \u0275\u0275text(4); 934 \u0275\u0275elementEnd(); 935 \u0275\u0275elementStart(5, "span"); 936 \u0275\u0275text(6); 937 \u0275\u0275pipe(7, "translate"); 938 \u0275\u0275elementEnd()(); 939 } 940 if (rf & 2) { 941 const preset_r8 = ctx; 942 const ctx_r0 = \u0275\u0275nextContext(2); 943 \u0275\u0275advance(2); 944 \u0275\u0275textInterpolate(preset_r8.name); 945 \u0275\u0275advance(2); 946 \u0275\u0275textInterpolate(ctx_r0.getPersistentPresetContext(preset_r8)); 947 \u0275\u0275advance(2); 948 \u0275\u0275textInterpolate4(" X: ", preset_r8.x, " cm \xB7 Y: ", preset_r8.y, " cm \xB7 ", \u0275\u0275pipeBind1(7, 6, "settings.persistentPosition.sourceLabel"), ": ", ctx_r0.getPersistentPresetSource(preset_r8), " "); 949 } 950} 951function SettingsPage_Conditional_204_Conditional_61_Template(rf, ctx) { 952 if (rf & 1) { 953 \u0275\u0275elementStart(0, "div", 124); 954 \u0275\u0275element(1, "ng-icon", 105); 955 \u0275\u0275elementStart(2, "span"); 956 \u0275\u0275text(3); 957 \u0275\u0275pipe(4, "translate"); 958 \u0275\u0275elementEnd()(); 959 } 960 if (rf & 2) { 961 \u0275\u0275advance(3); 962 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(4, 1, "settings.persistentPosition.missingPreset")); 963 } 964} 965function SettingsPage_Conditional_204_Conditional_62_Template(rf, ctx) { 966 if (rf & 1) { 967 \u0275\u0275elementStart(0, "div", 124); 968 \u0275\u0275element(1, "ng-icon", 105); 969 \u0275\u0275elementStart(2, "span"); 970 \u0275\u0275text(3); 971 \u0275\u0275pipe(4, "translate"); 972 \u0275\u0275elementEnd()(); 973 } 974 if (rf & 2) { 975 \u0275\u0275advance(3); 976 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(4, 1, "settings.persistentPosition.missingContext")); 977 } 978} 979function SettingsPage_Conditional_204_Conditional_63_Template(rf, ctx) { 980 if (rf & 1) { 981 \u0275\u0275elementStart(0, "div", 122); 982 \u0275\u0275element(1, "ng-icon", 107); 983 \u0275\u0275elementStart(2, "span"); 984 \u0275\u0275text(3); 985 \u0275\u0275pipe(4, "translate"); 986 \u0275\u0275elementEnd()(); 987 } 988 if (rf & 2) { 989 \u0275\u0275advance(3); 990 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(4, 1, "settings.persistentPosition.pending")); 991 } 992} 993function SettingsPage_Conditional_204_Conditional_64_Template(rf, ctx) { 994 if (rf & 1) { 995 \u0275\u0275elementStart(0, "div", 122); 996 \u0275\u0275element(1, "ng-icon", 107); 997 \u0275\u0275elementStart(2, "span"); 998 \u0275\u0275text(3); 999 \u0275\u0275pipe(4, "translate"); 1000 \u0275\u0275elementEnd()(); 1001 } 1002 if (rf & 2) { 1003 \u0275\u0275advance(3); 1004 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(4, 1, "settings.persistentPosition.temporaryPriority")); 1005 } 1006} 1007function SettingsPage_Conditional_204_Template(rf, ctx) { 1008 if (rf & 1) { 1009 \u0275\u0275elementStart(0, "div", 5)(1, "div", 6)(2, "div", 109); 1010 \u0275\u0275element(3, "ng-icon", 110); 1011 \u0275\u0275elementEnd(); 1012 \u0275\u0275elementStart(4, "h3"); 1013 \u0275\u0275text(5); 1014 \u0275\u0275pipe(6, "translate"); 1015 \u0275\u0275elementEnd()(); 1016 \u0275\u0275elementStart(7, "div", 9); 1017 \u0275\u0275template(8, SettingsPage_Conditional_204_Conditional_8_Template, 15, 11, "div", 10); 1018 \u0275\u0275elementStart(9, "div", 10)(10, "div", 11)(11, "div", 12); 1019 \u0275\u0275element(12, "ng-icon", 111); 1020 \u0275\u0275elementEnd(); 1021 \u0275\u0275elementStart(13, "div", 14)(14, "h4"); 1022 \u0275\u0275text(15); 1023 \u0275\u0275pipe(16, "translate"); 1024 \u0275\u0275elementEnd(); 1025 \u0275\u0275elementStart(17, "p"); 1026 \u0275\u0275text(18); 1027 \u0275\u0275pipe(19, "translate"); 1028 \u0275\u0275elementEnd()()(); 1029 \u0275\u0275elementStart(20, "ion-select", 112)(21, "ion-select-option", 113); 1030 \u0275\u0275text(22); 1031 \u0275\u0275pipe(23, "translate"); 1032 \u0275\u0275elementEnd(); 1033 \u0275\u0275elementStart(24, "ion-select-option", 114); 1034 \u0275\u0275text(25); 1035 \u0275\u0275pipe(26, "translate"); 1036 \u0275\u0275elementEnd(); 1037 \u0275\u0275elementStart(27, "ion-select-option", 115); 1038 \u0275\u0275text(28); 1039 \u0275\u0275pipe(29, "translate"); 1040 \u0275\u0275elementEnd()()(); 1041 \u0275\u0275elementStart(30, "div", 10)(31, "div", 11)(32, "div", 12); 1042 \u0275\u0275element(33, "ng-icon", 116); 1043 \u0275\u0275elementEnd(); 1044 \u0275\u0275elementStart(34, "div", 14)(35, "h4"); 1045 \u0275\u0275text(36); 1046 \u0275\u0275pipe(37, "translate"); 1047 \u0275\u0275elementEnd(); 1048 \u0275\u0275elementStart(38, "p"); 1049 \u0275\u0275text(39); 1050 \u0275\u0275pipe(40, "translate"); 1051 \u0275\u0275elementEnd()()(); 1052 \u0275\u0275element(41, "ion-input", 117); 1053 \u0275\u0275elementEnd(); 1054 \u0275\u0275elementStart(42, "div", 29)(43, "span"); 1055 \u0275\u0275text(44); 1056 \u0275\u0275pipe(45, "translate"); 1057 \u0275\u0275elementEnd()(); 1058 \u0275\u0275elementStart(46, "div", 118)(47, "div", 11)(48, "div", 12); 1059 \u0275\u0275element(49, "ng-icon", 119); 1060 \u0275\u0275elementEnd(); 1061 \u0275\u0275elementStart(50, "div", 14)(51, "h4"); 1062 \u0275\u0275text(52); 1063 \u0275\u0275pipe(53, "translate"); 1064 \u0275\u0275elementEnd(); 1065 \u0275\u0275elementStart(54, "p"); 1066 \u0275\u0275text(55); 1067 \u0275\u0275pipe(56, "translate"); 1068 \u0275\u0275elementEnd()()(); 1069 \u0275\u0275element(57, "ion-toggle", 120); 1070 \u0275\u0275elementEnd(); 1071 \u0275\u0275template(58, SettingsPage_Conditional_204_Conditional_58_Template, 15, 9, "div", 121)(59, SettingsPage_Conditional_204_Conditional_59_Template, 5, 3, "div", 122)(60, SettingsPage_Conditional_204_Conditional_60_Template, 8, 8, "div", 123)(61, SettingsPage_Conditional_204_Conditional_61_Template, 5, 3, "div", 124)(62, SettingsPage_Conditional_204_Conditional_62_Template, 5, 3, "div", 124)(63, SettingsPage_Conditional_204_Conditional_63_Template, 5, 3, "div", 122)(64, SettingsPage_Conditional_204_Conditional_64_Template, 5, 3, "div", 122); 1072 \u0275\u0275elementStart(65, "div", 24)(66, "div", 11)(67, "div", 12); 1073 \u0275\u0275element(68, "ng-icon", 20); 1074 \u0275\u0275elementEnd(); 1075 \u0275\u0275elementStart(69, "div", 14)(70, "h4"); 1076 \u0275\u0275text(71); 1077 \u0275\u0275pipe(72, "translate"); 1078 \u0275\u0275elementEnd(); 1079 \u0275\u0275elementStart(73, "p"); 1080 \u0275\u0275text(74); 1081 \u0275\u0275pipe(75, "translate"); 1082 \u0275\u0275elementEnd()()(); 1083 \u0275\u0275element(76, "ion-toggle", 125); 1084 \u0275\u0275elementEnd(); 1085 \u0275\u0275elementStart(77, "div", 24)(78, "div", 11)(79, "div", 12); 1086 \u0275\u0275element(80, "ng-icon", 126); 1087 \u0275\u0275elementEnd(); 1088 \u0275\u0275elementStart(81, "div", 14)(82, "h4"); 1089 \u0275\u0275text(83); 1090 \u0275\u0275pipe(84, "translate"); 1091 \u0275\u0275elementEnd(); 1092 \u0275\u0275elementStart(85, "p"); 1093 \u0275\u0275text(86); 1094 \u0275\u0275pipe(87, "translate"); 1095 \u0275\u0275elementEnd()()(); 1096 \u0275\u0275element(88, "ion-toggle", 127); 1097 \u0275\u0275elementEnd(); 1098 \u0275\u0275elementStart(89, "div", 24)(90, "div", 11)(91, "div", 12); 1099 \u0275\u0275element(92, "ng-icon", 128); 1100 \u0275\u0275elementEnd(); 1101 \u0275\u0275elementStart(93, "div", 14)(94, "h4"); 1102 \u0275\u0275text(95); 1103 \u0275\u0275pipe(96, "translate"); 1104 \u0275\u0275elementEnd(); 1105 \u0275\u0275elementStart(97, "p"); 1106 \u0275\u0275text(98); 1107 \u0275\u0275pipe(99, "translate"); 1108 \u0275\u0275elementEnd()()(); 1109 \u0275\u0275element(100, "ion-toggle", 129); 1110 \u0275\u0275elementEnd(); 1111 \u0275\u0275elementStart(101, "div", 24)(102, "div", 11)(103, "div", 12); 1112 \u0275\u0275element(104, "ng-icon", 60); 1113 \u0275\u0275elementEnd();
1114 \u0275\u0275elementStart(105, "div", 14)(106, "h4"); 1115 \u0275\u0275text(107); 1116 \u0275\u0275pipe(108, "translate"); 1117 \u0275\u0275elementEnd(); 1118 \u0275\u0275elementStart(109, "p"); 1119 \u0275\u0275text(110); 1120 \u0275\u0275pipe(111, "translate"); 1121 \u0275\u0275elementEnd()()(); 1122 \u0275\u0275element(112, "ion-toggle", 130); 1123 \u0275\u0275elementEnd()()(); 1124 } 1125 if (rf & 2) { 1126 let tmp_16_0; 1127 const ctx_r0 = \u0275\u0275nextContext(); 1128 \u0275\u0275advance(5); 1129 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(6, 26, "settings.advanced.title")); 1130 \u0275\u0275advance(3); 1131 \u0275\u0275conditional(ctx_r0.showApiUrlSection ? 8 : -1); 1132 \u0275\u0275advance(7); 1133 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(16, 28, "settings.bluetooth.scanMode.title")); 1134 \u0275\u0275advance(3); 1135 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(19, 30, "settings.bluetooth.scanMode.description")); 1136 \u0275\u0275advance(2); 1137 \u0275\u0275property("selectedText", ctx_r0.bleScanModeLabel); 1138 \u0275\u0275advance(2); 1139 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(23, 32, "settings.bluetooth.scanModeOptions.lowLatency")); 1140 \u0275\u0275advance(3); 1141 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(26, 34, "settings.bluetooth.scanModeOptions.balanced")); 1142 \u0275\u0275advance(3); 1143 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(29, 36, "settings.bluetooth.scanModeOptions.lowPower")); 1144 \u0275\u0275advance(8); 1145 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(37, 38, "settings.bluetooth.tagPrefix.title")); 1146 \u0275\u0275advance(3); 1147 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(40, 40, "settings.bluetooth.tagPrefix.description")); 1148 \u0275\u0275advance(5); 1149 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(45, 42, "settings.advanced.debug")); 1150 \u0275\u0275advance(8); 1151 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(53, 44, "settings.persistentPosition.title")); 1152 \u0275\u0275advance(3); 1153 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(56, 46, "settings.persistentPosition.description")); 1154 \u0275\u0275advance(2); 1155 \u0275\u0275property("disabled", !ctx_r0.persistentPositionCanBeEnabled); 1156 \u0275\u0275advance(); 1157 \u0275\u0275conditional(ctx_r0.debugPositionPresets.length > 0 || ctx_r0.hasMissingPersistentPreset ? 58 : 59); 1158 \u0275\u0275advance(2); 1159 \u0275\u0275conditional((tmp_16_0 = ctx_r0.selectedPersistentPositionPreset) ? 60 : -1, tmp_16_0); 1160 \u0275\u0275advance(); 1161 \u0275\u0275conditional(ctx_r0.hasMissingPersistentPreset || ctx_r0.debugPositionOverrideState.persistentValidity === "missing-preset" ? 61 : ctx_r0.debugPositionOverrideState.persistentValidity === "missing-context" ? 62 : ctx_r0.debugPositionOverrideState.persistentValidity === "pending" ? 63 : -1); 1162 \u0275\u0275advance(3); 1163 \u0275\u0275conditional(ctx_r0.debugPositionOverrideState.origin === "temporary" && ctx_r0.debugPositionOverrideState.persistentConfig.enabled ? 64 : -1); 1164 \u0275\u0275advance(7); 1165 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(72, 48, "settings.navigationSection.dynamicRotation.title")); 1166 \u0275\u0275advance(3); 1167 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(75, 50, "settings.navigationSection.dynamicRotation.description")); 1168 \u0275\u0275advance(9); 1169 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(84, 52, "settings.navigationSection.beaconDebugLogging.title")); 1170 \u0275\u0275advance(3); 1171 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(87, 54, "settings.navigationSection.beaconDebugLogging.description")); 1172 \u0275\u0275advance(9); 1173 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(96, 56, "settings.signal.recorder.panel")); 1174 \u0275\u0275advance(3); 1175 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(99, 58, "settings.signal.recorder.panel.description")); 1176 \u0275\u0275advance(9); 1177 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(108, 60, "settings.navigation.clampGpsOutside.title")); 1178 \u0275\u0275advance(3); 1179 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(111, 62, "settings.navigation.clampGpsOutside.description")); 1180 } 1181} 1182function SettingsPage_Conditional_205_Template(rf, ctx) { 1183 if (rf & 1) { 1184 \u0275\u0275elementStart(0, "div", 5)(1, "div", 6)(2, "div", 136); 1185 \u0275\u0275element(3, "ng-icon", 137); 1186 \u0275\u0275elementEnd(); 1187 \u0275\u0275elementStart(4, "h3"); 1188 \u0275\u0275text(5); 1189 \u0275\u0275pipe(6, "translate"); 1190 \u0275\u0275elementEnd()(); 1191 \u0275\u0275elementStart(7, "div", 9)(8, "div", 24)(9, "div", 11)(10, "div", 12); 1192 \u0275\u0275element(11, "ng-icon", 138); 1193 \u0275\u0275elementEnd(); 1194 \u0275\u0275elementStart(12, "div", 14)(13, "h4"); 1195 \u0275\u0275text(14); 1196 \u0275\u0275pipe(15, "translate"); 1197 \u0275\u0275elementEnd(); 1198 \u0275\u0275elementStart(16, "p"); 1199 \u0275\u0275text(17); 1200 \u0275\u0275pipe(18, "translate"); 1201 \u0275\u0275elementEnd()()(); 1202 \u0275\u0275element(19, "ion-toggle", 139); 1203 \u0275\u0275elementEnd(); 1204 \u0275\u0275elementStart(20, "div", 24)(21, "div", 11)(22, "div", 12); 1205 \u0275\u0275element(23, "ng-icon", 140); 1206 \u0275\u0275elementEnd(); 1207 \u0275\u0275elementStart(24, "div", 14)(25, "h4"); 1208 \u0275\u0275text(26); 1209 \u0275\u0275pipe(27, "translate"); 1210 \u0275\u0275elementEnd(); 1211 \u0275\u0275elementStart(28, "p"); 1212 \u0275\u0275text(29); 1213 \u0275\u0275pipe(30, "translate"); 1214 \u0275\u0275elementEnd()()(); 1215 \u0275\u0275element(31, "ion-toggle", 141); 1216 \u0275\u0275elementEnd(); 1217 \u0275\u0275elementStart(32, "div", 10)(33, "div", 11)(34, "div", 12); 1218 \u0275\u0275element(35, "ng-icon", 62); 1219 \u0275\u0275elementEnd(); 1220 \u0275\u0275elementStart(36, "div", 14)(37, "h4"); 1221 \u0275\u0275text(38); 1222 \u0275\u0275pipe(39, "translate"); 1223 \u0275\u0275elementEnd(); 1224 \u0275\u0275elementStart(40, "p"); 1225 \u0275\u0275text(41); 1226 \u0275\u0275pipe(42, "translate"); 1227 \u0275\u0275elementEnd()()(); 1228 \u0275\u0275element(43, "ion-input", 142); 1229 \u0275\u0275elementEnd(); 1230 \u0275\u0275elementStart(44, "div", 29)(45, "span"); 1231 \u0275\u0275text(46); 1232 \u0275\u0275pipe(47, "translate"); 1233 \u0275\u0275elementEnd()(); 1234 \u0275\u0275elementStart(48, "div", 24)(49, "div", 11)(50, "div", 12); 1235 \u0275\u0275element(51, "ng-icon", 143); 1236 \u0275\u0275elementEnd(); 1237 \u0275\u0275elementStart(52, "div", 14)(53, "h4"); 1238 \u0275\u0275text(54); 1239 \u0275\u0275pipe(55, "translate"); 1240 \u0275\u0275elementEnd(); 1241 \u0275\u0275elementStart(56, "p"); 1242 \u0275\u0275text(57); 1243 \u0275\u0275pipe(58, "translate"); 1244 \u0275\u0275elementEnd()()(); 1245 \u0275\u0275element(59, "ion-toggle", 144); 1246 \u0275\u0275elementEnd(); 1247 \u0275\u0275elementStart(60, "div", 24)(61, "div", 11)(62, "div", 12); 1248 \u0275\u0275element(63, "ng-icon", 145); 1249 \u0275\u0275elementEnd(); 1250 \u0275\u0275elementStart(64, "div", 14)(65, "h4"); 1251 \u0275\u0275text(66); 1252 \u0275\u0275pipe(67, "translate"); 1253 \u0275\u0275elementEnd(); 1254 \u0275\u0275elementStart(68, "p"); 1255 \u0275\u0275text(69); 1256 \u0275\u0275pipe(70, "translate"); 1257 \u0275\u0275elementEnd()()(); 1258 \u0275\u0275element(71, "ion-toggle", 146); 1259 \u0275\u0275elementEnd()()(); 1260 } 1261 if (rf & 2) { 1262 \u0275\u0275advance(5); 1263 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(6, 12, "settings.appearance.title")); 1264 \u0275\u0275advance(9); 1265 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(15, 14, "settings.grid.enable.title")); 1266 \u0275\u0275advance(3);
1267 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(18, 16, "settings.grid.enable.description")); 1268 \u0275\u0275advance(9); 1269 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(27, 18, "settings.grid.show.title")); 1270 \u0275\u0275advance(3); 1271 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(30, 20, "settings.grid.show.description")); 1272 \u0275\u0275advance(9); 1273 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(39, 22, "settings.grid.size.title")); 1274 \u0275\u0275advance(3); 1275 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(42, 24, "settings.grid.size.description")); 1276 \u0275\u0275advance(5); 1277 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(47, 26, "settings.theme.title")); 1278 \u0275\u0275advance(8); 1279 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(55, 28, "settings.theme.pink.title")); 1280 \u0275\u0275advance(3); 1281 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(58, 30, "settings.theme.pink.description")); 1282 \u0275\u0275advance(9); 1283 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(67, 32, "settings.theme.rainbow.title")); 1284 \u0275\u0275advance(3); 1285 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(70, 34, "settings.theme.rainbow.description")); 1286 } 1287} 1288function SettingsPage_Conditional_206_Template(rf, ctx) { 1289 if (rf & 1) { 1290 \u0275\u0275elementStart(0, "div", 50)(1, "div", 6)(2, "div", 147); 1291 \u0275\u0275element(3, "ng-icon", 148); 1292 \u0275\u0275elementEnd(); 1293 \u0275\u0275elementStart(4, "h3"); 1294 \u0275\u0275text(5); 1295 \u0275\u0275pipe(6, "translate"); 1296 \u0275\u0275elementEnd(); 1297 \u0275\u0275elementStart(7, "ion-chip", 149); 1298 \u0275\u0275element(8, "ng-icon", 134); 1299 \u0275\u0275elementStart(9, "span"); 1300 \u0275\u0275text(10); 1301 \u0275\u0275pipe(11, "translate"); 1302 \u0275\u0275elementEnd()()(); 1303 \u0275\u0275elementStart(12, "div", 9)(13, "div", 24)(14, "div", 11)(15, "div", 12); 1304 \u0275\u0275element(16, "ng-icon", 30); 1305 \u0275\u0275elementEnd(); 1306 \u0275\u0275elementStart(17, "div", 14)(18, "h4"); 1307 \u0275\u0275text(19); 1308 \u0275\u0275pipe(20, "translate"); 1309 \u0275\u0275elementEnd(); 1310 \u0275\u0275elementStart(21, "p"); 1311 \u0275\u0275text(22); 1312 \u0275\u0275pipe(23, "translate"); 1313 \u0275\u0275elementEnd()()(); 1314 \u0275\u0275element(24, "ion-toggle", 150); 1315 \u0275\u0275elementEnd()()(); 1316 } 1317 if (rf & 2) { 1318 \u0275\u0275advance(5); 1319 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(6, 4, "settings.experimental.title")); 1320 \u0275\u0275advance(5); 1321 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(11, 6, "settings.experimental.chip")); 1322 \u0275\u0275advance(9); 1323 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(20, 8, "settings.experimental.buildingOutlines.title")); 1324 \u0275\u0275advance(3); 1325 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(23, 10, "settings.experimental.buildingOutlines.description")); 1326 } 1327} 1328var _SettingsPage = class _SettingsPage { 1329 constructor(fb, settingsService, authService, toastService, deviceDetection, languageService, beaconService, apiUrlService, alertController, translateService, debugControlService, databaseService) { 1330 var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G; 1331 this.fb = fb; 1332 this.settingsService = settingsService; 1333 this.authService = authService; 1334 this.toastService = toastService; 1335 this.deviceDetection = deviceDetection; 1336 this.languageService = languageService; 1337 this.beaconService = beaconService; 1338 this.apiUrlService = apiUrlService; 1339 this.alertController = alertController; 1340 this.translateService = translateService; 1341 this.debugControlService = debugControlService; 1342 this.databaseService = databaseService; 1343 this.showEasterEggSection = false; 1344 this.deviceCapabilities = null; 1345 this.showDeviceInfo = false; 1346 this.showReportButton = true; 1347 this.currentLanguage = "lv"; 1348 this.pendingLanguage = null; 1349 this.isAdmin = false; 1350 this.isWebShareSupported = false; 1351 this.debugPositionPresets = []; 1352 this.isProduction = environment.production; 1353 this.showApiUrlSection = false;
1354 this.availableApiUrls = []; 1355 this.selectedApiUrl = ""; 1356 this.currentApiUrlName = ""; 1357 this.confirm = () => __async(this, null, function* () { 1358 const _a2 = this.settingsForm.value, { persistentPositionEnabled, persistentPositionPresetId } = _a2, settingsUpdate = __objRest(_a2, ["persistentPositionEnabled", "persistentPositionPresetId"]); 1359 const positioningMode = settingsUpdate.positioningModeResponsive ? "RESPONSIVE" : "STABLE"; 1360 delete settingsUpdate.positioningModeResponsive; 1361 settingsUpdate.positioningMode = positioningMode; 1362 const settings = __spreadValues(__spreadValues({}, this.settingsService.currentSettings), settingsUpdate); 1363 this.settingsService.setSettings(settings); 1364 this.debugControlService.setPersistentPositionConfig({ 1365 enabled: persistentPositionEnabled === true, 1366 presetId: typeof persistentPositionPresetId === "string" && persistentPositionPresetId.trim() ? persistentPositionPresetId : null 1367 }); 1368 const filterKeys = [ 1369 "rssiFilterType", 1370 "kalmanProcessNoise", 1371 "kalmanMeasurementNoise", 1372 "kalmanEstimationError", 1373 "adaptiveEmaBaseAlpha", 1374 "adaptiveEmaOutlierThreshold", 1375 "simpleEmaAlpha", 1376 "simpleEmaOutlierThreshold" 1377 ]; 1378 if (filterKeys.some((key) => settingsUpdate.hasOwnProperty(key))) { 1379 this.beaconService.clearFilters(); 1380 console.log("Cleared beacon filters due to settings change"); 1381 } 1382 if (this.pendingLanguage) { 1383 yield this.languageService.setLanguage(this.pendingLanguage); 1384 this.pendingLanguage = null; 1385 } 1386 yield this.toastService.showSuccess(this.translateService.instant("settings.toasts.saved"), 2e3); 1387 }); 1388 const currentSettings = this.settingsService.currentSettings; 1389 const persistentPosition = this.debugControlService.persistentPositionConfig; 1390 this.debugPositionOverrideState = this.debugControlService.overrideState; 1391 this.settingsForm = this.fb.group({ 1392 // User Preferences 1393 showCompactMenu: [currentSettings.showCompactMenu], 1394 tagAllowedPrefix: [currentSettings.tagAllowedPrefix, Validators.required], 1395 bleScanMode: [currentSettings.bleScanMode, Validators.required], 1396 // Navigation Settings 1397 enableAutoCenterCountdown: [(_a = currentSettings.enableAutoCenterCountdown) != null ? _a : true], 1398 mapRotationMode: [(_b = currentSettings.mapRotationMode) != null ? _b : "heading", Validators.required], 1399 voiceNavigationEnabled: [(_c = currentSettings.voiceNavigationEnabled) != null ? _c : false], 1400 keepScreenAwakeDuringNavigation: [(_d = currentSettings.keepScreenAwakeDuringNavigation) != null ? _d : true], 1401 showNavigationViewTuningControls: [(_e = currentSettings.showNavigationViewTuningControls) != null ? _e : false], 1402 navigationSurfaceProjectionEnabled: [(_f = currentSettings.navigationSurfaceProjectionEnabled) != null ? _f : false], 1403 showNavigationLightingTuningControls: [(_g = currentSettings.showNavigationLightingTuningControls) != null ? _g : false], 1404 showNavigationModelTuningControls: [(_h = currentSettings.showNavigationModelTuningControls) != null ? _h : false], 1405 // Advanced Navigation (Admin) 1406 enableDynamicRotationSync: [(_i = currentSettings.enableDynamicRotationSync) != null ? _i : true], 1407 forceDualMode: [(_j = currentSettings.forceDualMode) != null ? _j : true], 1408 enableSmartSourceSwitching: [(_k = currentSettings.enableSmartSourceSwitching) != null ? _k : true], 1409 forceBeaconOnlyMode: [(_l = currentSettings.forceBeaconOnlyMode) != null ? _l : false], 1410 enableBeaconDebugLogging: [(_m = currentSettings.enableBeaconDebugLogging) != null ? _m : false], 1411 positioningModeResponsive: [((_n = currentSettings.positioningMode) != null ? _n : "RESPONSIVE") === "RESPONSIVE"], 1412 enableSegmentHysteresis: [(_o = currentSettings.enableSegmentHysteresis) != null ? _o : false], 1413 segmentHysteresisThreshold: [(_p = currentSettings.segmentHysteresisThreshold) != null ? _p : 100, [Validators.required, Validators.min(50), Validators.max(500)]], 1414 clampGpsOutsideBuildings: [(_q = currentSettings.clampGpsOutsideBuildings) != null ? _q : false], 1415 // Rendering Settings 1416 renderingMode: [(_r = currentSettings.renderingMode) != null ? _r : "auto", Validators.required], 1417 openMapsEnabled: [(_s = currentSettings.openMapsEnabled) != null ? _s : true], 1418 // Signal Processing (Admin) 1419 rssiFilterType: [(_t = currentSettings.rssiFilterType) != null ? _t : "none", Validators.required], 1420 kalmanProcessNoise: [(_u = currentSettings.kalmanProcessNoise) != null ? _u : 1, [Validators.required, Validators.min(0.1)]], 1421 kalmanMeasurementNoise: [(_v = currentSettings.kalmanMeasurementNoise) != null ? _v : 4, [Validators.required, Validators.min(0.1)]], 1422 kalmanEstimationError: [(_w = currentSettings.kalmanEstimationError) != null ? _w : 1, [Validators.required, Validators.min(0.1)]], 1423 adaptiveEmaBaseAlpha: [(_x = currentSettings.adaptiveEmaBaseAlpha) != null ? _x : 0.3, [Validators.required, Validators.min(0.01), Validators.max(1)]], 1424 adaptiveEmaOutlierThreshold: [(_y = currentSettings.adaptiveEmaOutlierThreshold) != null ? _y : 2.5, [Validators.required, Validators.min(1), Validators.max(5)]], 1425 simpleEmaAlpha: [(_z = currentSettings.simpleEmaAlpha) != null ? _z : 0.35, [Validators.required, Validators.min(0.01), Validators.max(1)]], 1426 simpleEmaOutlierThreshold: [(_A = currentSettings.simpleEmaOutlierThreshold) != null ? _A : 2.5, [Validators.required, Validators.min(1), Validators.max(5)]], 1427 enableGraphKalmanFilter: [(_B = currentSettings.enableGraphKalmanFilter) != null ? _B : true], 1428 kalmanMaxVelocity: [(_C = currentSettings.kalmanMaxVelocity) != null ? _C : 200, [Validators.required, Validators.min(50), Validators.max(500)]], 1429 kalmanVelocityDecay: [(_D = currentSettings.kalmanVelocityDecay) != null ? _D : 0.95, [Validators.required, Validators.min(0.8), Validators.max(1)]], 1430 kalmanPathSnapThreshold: [(_E = currentSettings.kalmanPathSnapThreshold) != null ? _E : 100, [Validators.required, Validators.min(10), Validators.max(300)]], 1431 // Grid Settings (Admin) 1432 gridEnabled: [currentSettings.gridEnabled], 1433 gridSize: [currentSettings.gridSize, [Validators.required, Validators.min(10)]], 1434 gridVisible: [currentSettings.gridVisible], 1435 // Signal Recorder (Admin) 1436 showSignalRecorderPanel: [(_F = currentSettings.showSignalRecorderPanel) != null ? _F : false], 1437 // Appearance (Admin) 1438 enablePinkTheme: [currentSettings.enablePinkTheme || false], 1439 enableRainbowTheme: [currentSettings.enableRainbowTheme || false], 1440 // Experimental (Admin) 1441 enableBuildingOutlineMerging: [(_G = currentSettings.enableBuildingOutlineMerging) != null ? _G : false], 1442 // Persistent debug position (Admin, stored by DebugControlService) 1443 persistentPositionEnabled: [persistentPosition.enabled], 1444 persistentPositionPresetId: [persistentPosition.presetId] 1445 }); 1446 } 1447 ngOnInit() { 1448 this.currentLanguage = this.languageService.getCurrentLanguage(); 1449 this.languageService.currentLanguage$.subscribe((language) => { 1450 this.currentLanguage = language; 1451 }); 1452 this.isWebShareSupported = "share" in navigator; 1453 this.authService.user$.pipe(take(1)).subscribe((user) => { 1454 if ((user == null ? void 0 : user.email) === "[email protected]" || (user == null ? void 0 : user.email) === "[email protected]" || (user == null ? void 0 : user.email) === "[email protected]" || (user == null ? void 0 : user.email) === "[email protected]") { 1455 this.showEasterEggSection = true; 1456 } 1457 this.isAdmin = this.authService.hasRole(UserRole.Admin); 1458 this.showApiUrlSection = !this.isProduction || this.isProduction && this.isAdmin; 1459 }); 1460 this.availableApiUrls = this.apiUrlService.getAvailableUrls(); 1461 this.selectedApiUrl = this.apiUrlService.getSelectedUrl(); 1462 this.currentApiUrlName = this.apiUrlService.getSelectedUrlName(); 1463 this.loadDeviceCapabilities(); 1464 this.debugControlService.presets$.subscribe((presets) => { 1465 this.debugPositionPresets = presets; 1466 }); 1467 this.debugControlService.overrideState$.subscribe((state) => { 1468 this.debugPositionOverrideState = state; 1469 }); 1470 } 1471 loadDeviceCapabilities() { 1472 return __async(this, null, function* () { 1473 this.deviceCapabilities = this.settingsService.getDeviceCapabilities(); 1474 if (!this.deviceCapabilities) { 1475 try { 1476 this.deviceCapabilities = yield this.deviceDetection.detectDeviceCapabilities(); 1477 } catch (error) { 1478 console.error("Failed to detect device capabilities:", error); 1479 } 1480 } 1481 }); 1482 } 1483 onPositioningModeChange() { 1484 return __async(this, null, function* () { 1485 const alert = yield this.alertController.create({ 1486 header: this.translateService.instant("settings.alerts.positioningModeChanged.title"), 1487 message: this.translateService.instant("settings.alerts.positioningModeChanged.message"), 1488 buttons: [ 1489 { text: this.translateService.instant("settings.alerts.later"), role: "cancel" }, 1490 { 1491 text: this.translateService.instant("settings.alerts.restartNow"), 1492 handler: () => { 1493 window.location.reload(); 1494 } 1495 } 1496 ] 1497 }); 1498 yield alert.present(); 1499 }); 1500 } 1501 onLanguageChange(languageCode) { 1502 this.pendingLanguage = languageCode;
1503 } 1504 resetDeviceDetection() { 1505 return __async(this, null, function* () { 1506 yield this.settingsService.resetAutoDetection(); 1507 yield this.loadDeviceCapabilities(); 1508 yield this.toastService.showSuccess(this.translateService.instant("settings.toasts.deviceDetectionReset"), 3e3); 1509 }); 1510 } 1511 toggleDeviceInfo() { 1512 this.showDeviceInfo = !this.showDeviceInfo; 1513 } 1514 reportFlickering() { 1515 return __async(this, null, function* () { 1516 const confirm = window.confirm(this.translateService.instant("settings.confirmations.flickeringReport")); 1517 if (confirm) { 1518 this.deviceDetection.reportDeviceIssue("flickering", `Rendering mode: ${this.currentSettings.renderingMode}`); 1519 yield this.toastService.showWarning(this.translateService.instant("settings.toasts.reportThanks"), 4e3); 1520 } 1521 }); 1522 } 1523 onApiUrlChange() { 1524 return __async(this, null, function* () { 1525 if (!this.selectedApiUrl && this.selectedApiUrl !== "") { 1526 return; 1527 } 1528 const confirmMessage = this.isProduction ? this.translateService.instant("settings.confirmations.backendChangeProduction") : this.translateService.instant("settings.confirmations.backendChangeDev"); 1529 const confirmed = window.confirm(confirmMessage); 1530 if (confirmed) { 1531 try { 1532 yield this.apiUrlService.setSelectedUrl(this.selectedApiUrl); 1533 this.currentApiUrlName = this.apiUrlService.getSelectedUrlName(); 1534 yield this.toastService.showSuccess(this.translateService.instant("settings.toasts.backendChanged", { name: this.currentApiUrlName }), 4e3); 1535 } catch (error) { 1536 console.error("Failed to change API URL:", error); 1537 yield this.toastService.showError(this.translateService.instant("settings.toasts.backendChangeFailed")); 1538 this.selectedApiUrl = this.apiUrlService.getSelectedUrl(); 1539 } 1540 } else { 1541 this.selectedApiUrl = this.apiUrlService.getSelectedUrl(); 1542 } 1543 }); 1544 } 1545 get currentSettings() { 1546 return this.settingsService.currentSettings; 1547 } 1548 get selectedLanguage() { 1549 var _a; 1550 return (_a = this.pendingLanguage) != null ? _a : this.currentLanguage; 1551 } 1552 get selectedPersistentPositionPreset() { 1553 var _a, _b; 1554 const presetId = (_a = this.settingsForm.get("persistentPositionPresetId")) == null ? void 0 : _a.value; 1555 return (_b = this.debugPositionPresets.find((preset) => preset.id === presetId)) != null ? _b : null; 1556 } 1557 get hasMissingPersistentPreset() { 1558 var _a; 1559 const presetId = (_a = this.settingsForm.get("persistentPositionPresetId")) == null ? void 0 : _a.value; 1560 return Boolean(presetId && !this.selectedPersistentPositionPreset); 1561 } 1562 get persistentPositionCanBeEnabled() { 1563 var _a; 1564 return this.debugPositionPresets.length > 0 || this.hasMissingPersistentPreset || ((_a = this.settingsForm.get("persistentPositionEnabled")) == null ? void 0 : _a.value) === true; 1565 } 1566 getPersistentPresetContext(preset) { 1567 var _a, _b, _c, _d; 1568 if (preset.isOutdoor) { 1569 const campus = preset.campusId ? this.databaseService.Models.get(preset.campusId) : void 0; 1570 return (_a = campus == null ? void 0 : campus.entity.name) != null ? _a : this.translateService.instant("settings.persistentPosition.outdoor"); 1571 } 1572 const floor = this.databaseService.Models.get(preset.floorId); 1573 const building = this.databaseService.Models.get(preset.buildingId); 1574 const campusName = (_d = (_b = floor == null ? void 0 : floor.campus) == null ? void 0 : _b.entity.name) != null ? _d : (_c = building == null ? void 0 : building.campus) == null ? void 0 : _c.entity.name; 1575 const buildingName = building == null ? void 0 : building.entity.name; 1576 const floorName = floor == null ? void 0 : floor.entity.name; 1577 return [campusName, buildingName, floorName].filter(Boolean).join(" / ") || this.translateService.instant("settings.persistentPosition.unknownContext"); 1578 } 1579 getPersistentPresetSource(preset) { 1580 if (!preset.source) { 1581 return this.translateService.instant("settings.persistentPosition.source.auto"); 1582 }
1583 return this.translateService.instant(preset.source === "gps" ? "settings.persistentPosition.source.gps" : "settings.persistentPosition.source.beacon"); 1584 } 1585 get bleScanModeLabel() { 1586 var _a; 1587 const value = (_a = this.settingsForm.get("bleScanMode")) == null ? void 0 : _a.value; 1588 const keyMap = { 1589 "low_latency": "settings.bluetooth.scanModeOptions.lowLatency", 1590 "balanced": "settings.bluetooth.scanModeOptions.balanced", 1591 "low_power": "settings.bluetooth.scanModeOptions.lowPower" 1592 }; 1593 return keyMap[value] ? this.translateService.instant(keyMap[value]) : ""; 1594 } 1595 get rssiFilterTypeLabel() { 1596 var _a; 1597 const value = (_a = this.settingsForm.get("rssiFilterType")) == null ? void 0 : _a.value; 1598 const keyMap = { 1599 "none": "settings.rssiFilter.options.none", 1600 "kalman": "settings.rssiFilter.options.kalman", 1601 "adaptiveEma": "settings.rssiFilter.options.adaptiveEma", 1602 "simpleEma": "settings.rssiFilter.options.simpleEma", 1603 "simpleSma": "settings.rssiFilter.options.simpleSma" 1604 }; 1605 return keyMap[value] ? this.translateService.instant(keyMap[value]) : ""; 1606 } 1607 get renderingModeLabel() { 1608 var _a; 1609 const value = (_a = this.settingsForm.get("renderingMode")) == null ? void 0 : _a.value; 1610 const keyMap = { 1611 "auto": "settings.renderingMode.options.auto", 1612 "2d": "settings.renderingMode.options.2d", 1613 "3d": "settings.renderingMode.options.3d" 1614 }; 1615 return keyMap[value] ? this.translateService.instant(keyMap[value]) : ""; 1616 } 1617 get mapRotationModeLabel() { 1618 var _a; 1619 const value = (_a = this.settingsForm.get("mapRotationMode")) == null ? void 0 : _a.value; 1620 const keyMap = { 1621 "heading": "settings.navigation.rotation.heading.title", 1622 "north": "settings.navigation.rotation.north.title" 1623 }; 1624 return keyMap[value] ? this.translateService.instant(keyMap[value]) : ""; 1625 } 1626}; 1627_SettingsPage.\u0275fac = function SettingsPage_Factory(__ngFactoryType__) { 1628 return new (__ngFactoryType__ || _SettingsPage)(\u0275\u0275directiveInject(FormBuilder), \u0275\u0275directiveInject(SettingsService), \u0275\u0275directiveInject(AuthService), \u0275\u0275directiveInject(ToastService), \u0275\u0275directiveInject(DeviceDetectionService), \u0275\u0275directiveInject(LanguageService), \u0275\u0275directiveInject(BeaconService), \u0275\u0275directiveInject(ApiUrlService), \u0275\u0275directiveInject(AlertController), \u0275\u0275directiveInject(TranslateService), \u0275\u0275directiveInject(DebugControlService), \u0275\u0275directiveInject(DatabaseService)); 1629}; 1630_SettingsPage.\u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _SettingsPage, selectors: [["app-settings"]], features: [\u0275\u0275ProvidersFeature([], [provideIcons({ 1631 lucideSave, 1632 lucideSettings2, 1633 lucideMenu, 1634 lucideBug, 1635 lucideBluetooth, 1636 lucideActivity, 1637 lucideTag, 1638 lucideGrid3x3, 1639 lucideToggleLeft, 1640 lucideEye, 1641 lucideRuler, 1642 lucideRadar, 1643 lucideOctagon, 1644 lucideTrendingUp, 1645 lucideTrendingDown, 1646 lucideTimer, 1647 lucideRefreshCw, 1648 lucideRotateCw, 1649 lucideZap, 1650 lucideTarget, 1651 lucideHistory, 1652 lucideFilter, 1653 lucideWaves, 1654 lucideSignalLow, 1655 lucideSignalHigh, 1656 lucideChartLine, 1657 lucideTimerOff, 1658 lucideNavigation2, 1659 lucideCircleDot, 1660 lucideMapPin, 1661 lucideRoute, 1662 lucideSparkles, 1663 lucidePalette, 1664 lucideRainbow, 1665 lucideBrain, 1666 lucideMove, 1667 lucideGauge, 1668 lucideCircle, 1669 lucideMonitor, 1670 lucideHand, 1671 lucidePaintbrush, 1672 lucideDroplets, 1673 lucideCpu, 1674 lucideRadio, 1675 lucideNavigation, 1676 lucideMoveHorizontal, 1677 lucideLayers, 1678 lucideArrowUpDown, 1679 lucideBell, 1680 lucideMousePointer, 1681 lucideChevronUp, 1682 lucideChevronDown, 1683 lucideTriangleAlert, 1684 lucideInfo, 1685 lucideUsers, 1686 lucideGitBranchPlus, 1687 lucideSettings, 1688 lucideClock, 1689 lucideGlobe, 1690 lucidePlay, 1691 lucideSquare, 1692 lucideDownload, 1693 lucideFileText, 1694 lucideTrash2, 1695 lucideFile, 1696 lucideShare, 1697 lucideSmartphone, 1698 lucideLock, 1699 lucideMagnet, 1700 lucideSatellite, 1701 lucideBuilding2, 1702 lucideRouteIcon: lucideRoute, 1703 lucideSlidersHorizontal, 1704 lucideSun, 1705 lucideVolume2 1706})])], decls: 210, vars: 113, consts: [[3, "translucent"], ["slot", "start"], [3, "fullscreen"], [1, "settings-container"], [3, "ngSubmit", "formGroup"], [1, "settings-section"], [1, "section-header"], [1, "section-icon"], ["name", "lucideGlobe", "size", "1.5em"], [1, "settings-list"], [1, "setting-item"], [1, "setting-content"], [1, "setting-icon"], ["name", "lucideGlobe", "size", "1.3em"], [1, "setting-details"], ["interface", "popover", "mode", "ios", 1, "custom-select", 3, "ionChange", "value"], ["value", "lv"], ["value", "en"], ["value", "de"], ["value", "ru"], ["name", "lucideRotateCw", "size", "1.3em"], ["formControlName", "mapRotationMode", "interface", "popover", "mode", "ios", 1, "custom-select", 3, "selectedText"], ["value", "heading"], ["value", "north"], [1, "setting-item", "toggle-item"], ["name", "lucideVolume2", "size", "1.3em"], ["formControlName", "voiceNavigationEnabled", "mode", "ios"], ["name", "lucideSmartphone", "size", "1.3em"], ["formControlName", "keepScreenAwakeDuringNavigation", "mode", "ios"], [1, "setting-divider"], ["name", "lucideLayers", "size", "1.3em"], ["formControlName", "renderingMode", "interface", "popover", "mode", "ios", 1, "custom-select", 3, "selectedText"], ["value", "auto"], ["value", "2d"], ["value", "3d"], ["formControlName", "openMapsEnabled", "mode", "ios"], ["name", "lucideTimer", "size", "1.3em"], ["formControlName", "enableAutoCenterCountdown", "mode", "ios"], ["name", "lucideSlidersHorizontal", "size", "1.3em"], ["formControlName", "showNavigationViewTuningControls", "mode", "ios"], ["formControlName", "navigationSurfaceProjectionEnabled", "mode", "ios"], ["name", "lucideSun", "size", "1.3em"], ["formControlName", "showNavigationLightingTuningControls", "mode", "ios"], ["name", "lucideMove", "size", "1.3em"], ["formControlName", "showNavigationModelTuningControls", "mode", "ios"], ["name", "lucideNavigation2", "size", "1.5em"], ["name", "lucideActivity", "size", "1.3em"], ["formControlName", "positioningModeResponsive", "mode", "ios", 3, "ionChange"], ["name", "lucideCpu", "size", "1.5em"], [1, "device-info-card"], [1, "settings-section", "experimental-section"], ["slot", "fixed", "vertical", "bottom", "horizontal", "end"], [3, "click", "disabled"], ["name", "lucideSave", "size", "1.5em"], ["name", "lucideTarget", "size", "1.3em"], ["formControlName", "enableSmartSourceSwitching", "mode", "ios"], ["name", "lucideRoute", "size", "1.3em"], ["formControlName", "enableSegmentHysteresis", "mode", "ios"], ["name", "lucideSatellite", "size", "1.3em"], ["formControlName", "forceDualMode", "mode", "ios"], ["name", "lucideRadio", "size", "1.3em"], ["formControlName", "forceBeaconOnlyMode", "mode", "ios"], ["name", "lucideRuler", "size", "1.3em"], ["formControlName", "segmentHysteresisThreshold", "type", "number", "min", "50", "max", "500", "step", "50", 1, "custom-input"], [1, "section-icon", "signal-processing"], ["name", "lucideActivity", "size", "1.5em"], ["name", "lucideFilter", "size", "1.3em"], ["formControlName", "rssiFilterType", "interface", "popover", "mode", "ios", 1, "custom-select", 3, "selectedText"], ["value", "none"], ["value", "kalman"], ["value", "adaptiveEma"], ["value", "simpleEma"], ["value", "simpleSma"], [1, "filter-parameters"], ["name", "lucideTrendingUp", "size", "1.3em"], ["formControlName", "enableGraphKalmanFilter", "mode", "ios"], ["formControlName", "kalmanProcessNoise", "type", "number", "step", "0.1", "placeholder", "1.0", 1, "custom-input"], ["name", "lucideRadar", "size", "1.3em"], ["formControlName", "kalmanMeasurementNoise", "type", "number", "step", "0.1", "placeholder", "4.0", 1, "custom-input"], ["formControlName", "kalmanEstimationError", "type", "number", "step", "0.1", "placeholder", "1.0", 1, "custom-input"], ["name", "lucideGauge", "size", "1.3em"], ["formControlName", "adaptiveEmaBaseAlpha", "type", "number", "step", "0.01", "min", "0.01", "max", "1.0", "placeholder", "0.3", 1, "custom-input"], ["name", "lucideTriangleAlert", "size", "1.3em"], ["formControlName", "adaptiveEmaOutlierThreshold", "type", "number", "step", "0.1", "min", "1.0", "max", "5.0", "placeholder", "2.5", 1, "custom-input"], ["formControlName", "simpleEmaAlpha", "type", "number", "step", "0.01", "min", "0.01", "max", "1.0", "placeholder", "0.35", 1, "custom-input"], ["formControlName", "simpleEmaOutlierThreshold", "type", "number", "step", "0.1", "min", "1.0", "max", "5.0", "placeholder", "2.5", 1, "custom-input"], ["name", "lucideZap", "size", "1.3em"], ["formControlName", "kalmanMaxVelocity", "type", "number", "min", "50", "max", "500", "step", "10", "placeholder", "200", 1, "custom-input"], ["name", "lucideTrendingDown", "size", "1.3em"], ["formControlName", "kalmanVelocityDecay", "type", "number", "step", "0.01", "min", "0.8", "max", "1.0", "placeholder", "0.95", 1, "custom-input"], ["name", "lucideMagnet", "size", "1.3em"], ["formControlName", "kalmanPathSnapThreshold", "type", "number", "min", "10", "max", "300", "step", "10", "placeholder", "100", 1, "custom-input"], [1, "device-header"], ["name", "lucideCpu", "size", "1.3em"], ["fill", "clear", "size", "small", 3, "click"], ["size", "1.2em", 3, "name"], [1, "device-info-grid"], [1, "info-item"], [1, "warning-chip"], [1, "info-chip"], [1, "device-actions"], ["size", "small", "fill", "outline", 3, "click"], ["name", "lucideRefreshCw", "size", "1em"], ["size", "small", "fill", "outline", "color", "warning"], ["color", "warning"], ["name", "lucideTriangleAlert", "size", "1em"], ["color", "medium"], ["name", "lucideInfo", "size", "1em"], ["size", "small", "fill", "outline", "color", "warning", 3, "click"], [1, "section-icon", "advanced"], ["name", "lucideSettings", "size", "1.5em"], ["name", "lucideBluetooth", "size", "1.3em"], ["formControlName", "bleScanMode", "interface", "popover", "mode", "ios", 1, "custom-select", 3, "selectedText"], ["value", "low_latency"], ["value", "balanced"], ["value", "low_power"], ["name", "lucideTag", "size", "1.3em"], ["formControlName", "tagAllowedPrefix", "type", "text", "placeholder", "e.g., KBPro", 1, "custom-input"], [1, "setting-item", "toggle-item", "persistent-position-toggle"], ["name", "lucideMapPin", "size", "1.3em"], ["formControlName", "persistentPositionEnabled", "mode", "ios", 3, "disabled"], [1, "setting-item", "persistent-position-selector"], [1, "persistent-position-message", "info-message"], [1, "persistent-position-summary"], [1, "persistent-position-message", "warning-message"], ["formControlName", "enableDynamicRotationSync", "mode", "ios"], ["name", "lucideBug", "size", "1.3em"], ["formControlName", "enableBeaconDebugLogging", "mode", "ios"], ["name", "lucideBell", "size", "1.3em"], ["formControlName", "showSignalRecorderPanel", "mode", "ios"], ["formControlName", "clampGpsOutsideBuildings", "mode", "ios"], [1, "warning-text"], ["interface", "action-sheet", "mode", "ios", 1, "custom-select", 3, "ngModelChange", "ionChange", "ngModel", "ngModelOptions"], [3, "value"], ["name", "lucideTriangleAlert", "size", "0.9em"], ["formControlName", "persistentPositionPresetId", "interface", "popover", "mode", "ios", 1, "custom-select", 3, "placeholder"], [1, "section-icon", "appearance"], ["name", "lucidePalette", "size", "1.5em"], ["name", "lucideGrid3x3", "size", "1.3em"], ["formControlName", "gridEnabled", "mode", "ios"], ["name", "lucideEye", "size", "1.3em"], ["formControlName", "gridVisible", "mode", "ios"], ["formControlName", "gridSize", "type", "number", "placeholder", "100", 1, "custom-input"], ["name", "lucidePalette", "size", "1.3em"], ["formControlName", "enablePinkTheme", "mode", "ios"], ["name", "lucideRainbow", "size", "1.3em"], ["formControlName", "enableRainbowTheme", "mode", "ios"], [1, "section-icon", "experimental"], ["name", "lucideTriangleAlert", "size", "1.5em"], ["color", "warning", 1, "experimental-chip"], ["formControlName", "enableBuildingOutlineMerging", "mode", "ios"]], template: function SettingsPage_Template(rf, ctx) { 1707 if (rf & 1) {
vendor: 10,112 bytes, lines 1708-1940
1708 \u0275\u0275elementStart(0, "ion-header", 0)(1, "ion-toolbar")(2, "ion-buttons", 1); 1709 \u0275\u0275element(3, "ion-menu-button"); 1710 \u0275\u0275elementEnd(); 1711 \u0275\u0275elementStart(4, "ion-title"); 1712 \u0275\u0275text(5); 1713 \u0275\u0275pipe(6, "translate"); 1714 \u0275\u0275elementEnd()()(); 1715 \u0275\u0275elementStart(7, "ion-content", 2)(8, "div", 3)(9, "form", 4); 1716 \u0275\u0275listener("ngSubmit", function SettingsPage_Template_form_ngSubmit_9_listener() { 1717 return ctx.confirm(); 1718 }); 1719 \u0275\u0275elementStart(10, "div", 5)(11, "div", 6)(12, "div", 7); 1720 \u0275\u0275element(13, "ng-icon", 8); 1721 \u0275\u0275elementEnd(); 1722 \u0275\u0275elementStart(14, "h3"); 1723 \u0275\u0275text(15); 1724 \u0275\u0275pipe(16, "translate"); 1725 \u0275\u0275elementEnd()(); 1726 \u0275\u0275elementStart(17, "div", 9)(18, "div", 10)(19, "div", 11)(20, "div", 12); 1727 \u0275\u0275element(21, "ng-icon", 13); 1728 \u0275\u0275elementEnd(); 1729 \u0275\u0275elementStart(22, "div", 14)(23, "h4"); 1730 \u0275\u0275text(24); 1731 \u0275\u0275pipe(25, "translate"); 1732 \u0275\u0275elementEnd(); 1733 \u0275\u0275elementStart(26, "p"); 1734 \u0275\u0275text(27); 1735 \u0275\u0275pipe(28, "translate"); 1736 \u0275\u0275elementEnd()()(); 1737 \u0275\u0275elementStart(29, "ion-select", 15); 1738 \u0275\u0275listener("ionChange", function SettingsPage_Template_ion_select_ionChange_29_listener($event) { 1739 return ctx.onLanguageChange($event.detail.value); 1740 }); 1741 \u0275\u0275elementStart(30, "ion-select-option", 16); 1742 \u0275\u0275text(31, "Latvie\u0161u (Latvian)"); 1743 \u0275\u0275elementEnd(); 1744 \u0275\u0275elementStart(32, "ion-select-option", 17); 1745 \u0275\u0275text(33, "English (English)"); 1746 \u0275\u0275elementEnd(); 1747 \u0275\u0275elementStart(34, "ion-select-option", 18); 1748 \u0275\u0275text(35, "Deutsch (German)"); 1749 \u0275\u0275elementEnd(); 1750 \u0275\u0275elementStart(36, "ion-select-option", 19); 1751 \u0275\u0275text(37, "\u0420\u0443\u0441\u0441\u043A\u0438\u0439 (Russian)"); 1752 \u0275\u0275elementEnd()()(); 1753 \u0275\u0275elementStart(38, "div", 10)(39, "div", 11)(40, "div", 12); 1754 \u0275\u0275element(41, "ng-icon", 20); 1755 \u0275\u0275elementEnd(); 1756 \u0275\u0275elementStart(42, "div", 14)(43, "h4"); 1757 \u0275\u0275text(44); 1758 \u0275\u0275pipe(45, "translate"); 1759 \u0275\u0275elementEnd(); 1760 \u0275\u0275elementStart(46, "p"); 1761 \u0275\u0275text(47); 1762 \u0275\u0275pipe(48, "translate"); 1763 \u0275\u0275elementEnd()()(); 1764 \u0275\u0275elementStart(49, "ion-select", 21)(50, "ion-select-option", 22); 1765 \u0275\u0275text(51); 1766 \u0275\u0275pipe(52, "translate"); 1767 \u0275\u0275elementEnd(); 1768 \u0275\u0275elementStart(53, "ion-select-option", 23); 1769 \u0275\u0275text(54); 1770 \u0275\u0275pipe(55, "translate"); 1771 \u0275\u0275elementEnd()()(); 1772 \u0275\u0275elementStart(56, "div", 24)(57, "div", 11)(58, "div", 12); 1773 \u0275\u0275element(59, "ng-icon", 25); 1774 \u0275\u0275elementEnd(); 1775 \u0275\u0275elementStart(60, "div", 14)(61, "h4"); 1776 \u0275\u0275text(62); 1777 \u0275\u0275pipe(63, "translate"); 1778 \u0275\u0275elementEnd(); 1779 \u0275\u0275elementStart(64, "p"); 1780 \u0275\u0275text(65); 1781 \u0275\u0275pipe(66, "translate"); 1782 \u0275\u0275elementEnd()()(); 1783 \u0275\u0275element(67, "ion-toggle", 26); 1784 \u0275\u0275elementEnd(); 1785 \u0275\u0275elementStart(68, "div", 24)(69, "div", 11)(70, "div", 12); 1786 \u0275\u0275element(71, "ng-icon", 27); 1787 \u0275\u0275elementEnd(); 1788 \u0275\u0275elementStart(72, "div", 14)(73, "h4"); 1789 \u0275\u0275text(74); 1790 \u0275\u0275pipe(75, "translate"); 1791 \u0275\u0275elementEnd(); 1792 \u0275\u0275elementStart(76, "p"); 1793 \u0275\u0275text(77); 1794 \u0275\u0275pipe(78, "translate"); 1795 \u0275\u0275elementEnd()()(); 1796 \u0275\u0275element(79, "ion-toggle", 28); 1797 \u0275\u0275elementEnd(); 1798 \u0275\u0275template(80, SettingsPage_Conditional_80_Template, 4, 3, "div", 29); 1799 \u0275\u0275elementStart(81, "div", 10)(82, "div", 11)(83, "div", 12); 1800 \u0275\u0275element(84, "ng-icon", 30); 1801 \u0275\u0275elementEnd(); 1802 \u0275\u0275elementStart(85, "div", 14)(86, "h4"); 1803 \u0275\u0275text(87); 1804 \u0275\u0275pipe(88, "translate"); 1805 \u0275\u0275elementEnd(); 1806 \u0275\u0275elementStart(89, "p"); 1807 \u0275\u0275text(90); 1808 \u0275\u0275pipe(91, "translate"); 1809 \u0275\u0275elementEnd()()(); 1810 \u0275\u0275elementStart(92, "ion-select", 31)(93, "ion-select-option", 32); 1811 \u0275\u0275text(94); 1812 \u0275\u0275pipe(95, "translate"); 1813 \u0275\u0275elementEnd(); 1814 \u0275\u0275elementStart(96, "ion-select-option", 33); 1815 \u0275\u0275text(97); 1816 \u0275\u0275pipe(98, "translate"); 1817 \u0275\u0275elementEnd(); 1818 \u0275\u0275elementStart(99, "ion-select-option", 34); 1819 \u0275\u0275text(100); 1820 \u0275\u0275pipe(101, "translate"); 1821 \u0275\u0275elementEnd()()(); 1822 \u0275\u0275elementStart(102, "div", 24)(103, "div", 11)(104, "div", 12); 1823 \u0275\u0275element(105, "ng-icon", 13); 1824 \u0275\u0275elementEnd(); 1825 \u0275\u0275elementStart(106, "div", 14)(107, "h4"); 1826 \u0275\u0275text(108); 1827 \u0275\u0275pipe(109, "translate"); 1828 \u0275\u0275elementEnd(); 1829 \u0275\u0275elementStart(110, "p"); 1830 \u0275\u0275text(111); 1831 \u0275\u0275pipe(112, "translate"); 1832 \u0275\u0275elementEnd()()(); 1833 \u0275\u0275element(113, "ion-toggle", 35); 1834 \u0275\u0275elementEnd(); 1835 \u0275\u0275elementStart(114, "div", 24)(115, "div", 11)(116, "div", 12); 1836 \u0275\u0275element(117, "ng-icon", 36); 1837 \u0275\u0275elementEnd(); 1838 \u0275\u0275elementStart(118, "div", 14)(119, "h4"); 1839 \u0275\u0275text(120); 1840 \u0275\u0275pipe(121, "translate"); 1841 \u0275\u0275elementEnd(); 1842 \u0275\u0275elementStart(122, "p"); 1843 \u0275\u0275text(123); 1844 \u0275\u0275pipe(124, "translate"); 1845 \u0275\u0275elementEnd()()(); 1846 \u0275\u0275element(125, "ion-toggle", 37); 1847 \u0275\u0275elementEnd(); 1848 \u0275\u0275elementStart(126, "div", 24)(127, "div", 11)(128, "div", 12); 1849 \u0275\u0275element(129, "ng-icon", 38); 1850 \u0275\u0275elementEnd(); 1851 \u0275\u0275elementStart(130, "div", 14)(131, "h4"); 1852 \u0275\u0275text(132); 1853 \u0275\u0275pipe(133, "translate"); 1854 \u0275\u0275elementEnd(); 1855 \u0275\u0275elementStart(134, "p"); 1856 \u0275\u0275text(135); 1857 \u0275\u0275pipe(136, "translate"); 1858 \u0275\u0275elementEnd()()(); 1859 \u0275\u0275element(137, "ion-toggle", 39); 1860 \u0275\u0275elementEnd(); 1861 \u0275\u0275elementStart(138, "div", 24)(139, "div", 11)(140, "div", 12); 1862 \u0275\u0275element(141, "ng-icon", 30); 1863 \u0275\u0275elementEnd(); 1864 \u0275\u0275elementStart(142, "div", 14)(143, "h4"); 1865 \u0275\u0275text(144); 1866 \u0275\u0275pipe(145, "translate"); 1867 \u0275\u0275elementEnd(); 1868 \u0275\u0275elementStart(146, "p"); 1869 \u0275\u0275text(147); 1870 \u0275\u0275pipe(148, "translate"); 1871 \u0275\u0275elementEnd()()(); 1872 \u0275\u0275element(149, "ion-toggle", 40); 1873 \u0275\u0275elementEnd(); 1874 \u0275\u0275elementStart(150, "div", 24)(151, "div", 11)(152, "div", 12); 1875 \u0275\u0275element(153, "ng-icon", 41); 1876 \u0275\u0275elementEnd(); 1877 \u0275\u0275elementStart(154, "div", 14)(155, "h4"); 1878 \u0275\u0275text(156); 1879 \u0275\u0275pipe(157, "translate"); 1880 \u0275\u0275elementEnd(); 1881 \u0275\u0275elementStart(158, "p"); 1882 \u0275\u0275text(159); 1883 \u0275\u0275pipe(160, "translate"); 1884 \u0275\u0275elementEnd()()(); 1885 \u0275\u0275element(161, "ion-toggle", 42); 1886 \u0275\u0275elementEnd(); 1887 \u0275\u0275elementStart(162, "div", 24)(163, "div", 11)(164, "div", 12); 1888 \u0275\u0275element(165, "ng-icon", 43); 1889 \u0275\u0275elementEnd(); 1890 \u0275\u0275elementStart(166, "div", 14)(167, "h4"); 1891 \u0275\u0275text(168); 1892 \u0275\u0275pipe(169, "translate"); 1893 \u0275\u0275elementEnd(); 1894 \u0275\u0275elementStart(170, "p"); 1895 \u0275\u0275text(171); 1896 \u0275\u0275pipe(172, "translate"); 1897 \u0275\u0275elementEnd()()(); 1898 \u0275\u0275element(173, "ion-toggle", 44); 1899 \u0275\u0275elementEnd()()(); 1900 \u0275\u0275elementStart(174, "div", 5)(175, "div", 6)(176, "div", 7); 1901 \u0275\u0275element(177, "ng-icon", 45); 1902 \u0275\u0275elementEnd(); 1903 \u0275\u0275elementStart(178, "h3"); 1904 \u0275\u0275text(179); 1905 \u0275\u0275pipe(180, "translate"); 1906 \u0275\u0275elementEnd()(); 1907 \u0275\u0275elementStart(181, "div", 9)(182, "div", 24)(183, "div", 11)(184, "div", 12); 1908 \u0275\u0275element(185, "ng-icon", 46); 1909 \u0275\u0275elementEnd(); 1910 \u0275\u0275elementStart(186, "div", 14)(187, "h4"); 1911 \u0275\u0275text(188); 1912 \u0275\u0275pipe(189, "translate"); 1913 \u0275\u0275elementEnd(); 1914 \u0275\u0275elementStart(190, "p"); 1915 \u0275\u0275text(191); 1916 \u0275\u0275pipe(192, "translate"); 1917 \u0275\u0275elementEnd()()(); 1918 \u0275\u0275elementStart(193, "ion-toggle", 47); 1919 \u0275\u0275listener("ionChange", function SettingsPage_Template_ion_toggle_ionChange_193_listener() { 1920 return ctx.onPositioningModeChange(); 1921 }); 1922 \u0275\u0275elementEnd()(); 1923 \u0275\u0275template(194, SettingsPage_Conditional_194_Template, 49, 25); 1924 \u0275\u0275elementEnd()(); 1925 \u0275\u0275template(195, SettingsPage_Conditional_195_Template, 58, 41, "div", 5); 1926 \u0275\u0275elementStart(196, "div", 5)(197, "div", 6)(198, "div", 7); 1927 \u0275\u0275element(199, "ng-icon", 48); 1928 \u0275\u0275elementEnd(); 1929 \u0275\u0275elementStart(200, "h3"); 1930 \u0275\u0275text(201); 1931 \u0275\u0275pipe(202, "translate"); 1932 \u0275\u0275elementEnd()(); 1933 \u0275\u0275template(203, SettingsPage_Conditional_203_Template, 11, 5, "ion-card", 49); 1934 \u0275\u0275elementEnd(); 1935 \u0275\u0275template(204, SettingsPage_Conditional_204_Template, 113, 64, "div", 5)(205, SettingsPage_Conditional_205_Template, 72, 36, "div", 5)(206, SettingsPage_Conditional_206_Template, 25, 12, "div", 50); 1936 \u0275\u0275elementEnd()()(); 1937 \u0275\u0275elementStart(207, "ion-fab", 51)(208, "ion-fab-button", 52); 1938 \u0275\u0275listener("click", function SettingsPage_Template_ion_fab_button_click_208_listener() { 1939 return ctx.confirm(); 1940 });
1941 \u0275\u0275element(209, "ng-icon", 53); 1942 \u0275\u0275elementEnd()(); 1943 } 1944 if (rf & 2) { 1945 \u0275\u0275property("translucent", true); 1946 \u0275\u0275advance(5); 1947 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(6, 47, "settings.title")); 1948 \u0275\u0275advance(2); 1949 \u0275\u0275property("fullscreen", true); 1950 \u0275\u0275advance(2); 1951 \u0275\u0275property("formGroup", ctx.settingsForm); 1952 \u0275\u0275advance(6); 1953 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(16, 49, "settings.userPreferences.title")); 1954 \u0275\u0275advance(9); 1955 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(25, 51, "language.selector.subtitle")); 1956 \u0275\u0275advance(3); 1957 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(28, 53, "settings.choose.language")); 1958 \u0275\u0275advance(2); 1959 \u0275\u0275property("value", ctx.selectedLanguage); 1960 \u0275\u0275advance(15); 1961 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(45, 55, "settings.navigation.rotation.title")); 1962 \u0275\u0275advance(3); 1963 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(48, 57, "settings.navigation.rotation.description")); 1964 \u0275\u0275advance(2); 1965 \u0275\u0275property("selectedText", ctx.mapRotationModeLabel); 1966 \u0275\u0275advance(2); 1967 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(52, 59, "settings.navigation.rotation.heading.title")); 1968 \u0275\u0275advance(3); 1969 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(55, 61, "settings.navigation.rotation.north.title")); 1970 \u0275\u0275advance(8); 1971 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(63, 63, "navigation.voice.enabled.title")); 1972 \u0275\u0275advance(3); 1973 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(66, 65, "navigation.voice.enabled.description")); 1974 \u0275\u0275advance(9); 1975 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(75, 67, "settings.navigation.keepScreenAwake.title")); 1976 \u0275\u0275advance(3); 1977 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(78, 69, "settings.navigation.keepScreenAwake.description")); 1978 \u0275\u0275advance(3); 1979 \u0275\u0275conditional(ctx.isAdmin ? 80 : -1); 1980 \u0275\u0275advance(7); 1981 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(88, 71, "settings.renderingMode.title")); 1982 \u0275\u0275advance(3); 1983 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(91, 73, "settings.renderingMode.description")); 1984 \u0275\u0275advance(2); 1985 \u0275\u0275property("selectedText", ctx.renderingModeLabel); 1986 \u0275\u0275advance(2); 1987 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(95, 75, "settings.renderingMode.options.auto")); 1988 \u0275\u0275advance(3); 1989 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(98, 77, "settings.renderingMode.options.2d")); 1990 \u0275\u0275advance(3); 1991 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(101, 79, "settings.renderingMode.options.3d")); 1992 \u0275\u0275advance(8); 1993 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(109, 81, "settings.openMaps.title")); 1994 \u0275\u0275advance(3); 1995 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(112, 83, "settings.openMaps.description")); 1996 \u0275\u0275advance(9); 1997 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(121, 85, "settings.navigation.autoCenter.title")); 1998 \u0275\u0275advance(3); 1999 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(124, 87, "settings.navigation.autoCenter.description")); 2000 \u0275\u0275advance(9); 2001 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(133, 89, "settings.navigation.viewTuning.title")); 2002 \u0275\u0275advance(3); 2003 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(136, 91, "settings.navigation.viewTuning.description")); 2004 \u0275\u0275advance(9); 2005 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(145, 93, "settings.navigation.surfaceProjection.title")); 2006 \u0275\u0275advance(3); 2007 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(148, 95, "settings.navigation.surfaceProjection.description")); 2008 \u0275\u0275advance(9); 2009 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(157, 97, "settings.navigation.lightingTuning.title")); 2010 \u0275\u0275advance(3); 2011 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(160, 99, "settings.navigation.lightingTuning.description")); 2012 \u0275\u0275advance(9); 2013 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(169, 101, "settings.navigation.modelTuning.title")); 2014 \u0275\u0275advance(3); 2015 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(172, 103, "settings.navigation.modelTuning.description")); 2016 \u0275\u0275advance(8); 2017 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(180, 105, "settings.navigationSection.title")); 2018 \u0275\u0275advance(9); 2019 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(189, 107, "settings.navigationSection.responsivePositioning.t
2019itle")); 2020 \u0275\u0275advance(3); 2021 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(192, 109, "settings.navigationSection.responsivePositioning.description")); 2022 \u0275\u0275advance(3); 2023 \u0275\u0275conditional(ctx.isAdmin ? 194 : -1); 2024 \u0275\u0275advance(); 2025 \u0275\u0275conditional(ctx.isAdmin ? 195 : -1); 2026 \u0275\u0275advance(6); 2027 \u0275\u0275textInterpolate(\u0275\u0275pipeBind1(202, 111, "settings.performance.title")); 2028 \u0275\u0275advance(2); 2029 \u0275\u0275conditional(ctx.deviceCapabilities ? 203 : -1); 2030 \u0275\u0275advance(); 2031 \u0275\u0275conditional(ctx.isAdmin ? 204 : -1); 2032 \u0275\u0275advance(); 2033 \u0275\u0275conditional(ctx.isAdmin ? 205 : -1); 2034 \u0275\u0275advance(); 2035 \u0275\u0275conditional(ctx.isAdmin ? 206 : -1); 2036 \u0275\u0275advance(2); 2037 \u0275\u0275property("disabled", !ctx.settingsForm.valid); 2038 } 2039}, dependencies: [ 2040 FormsModule, 2041 \u0275NgNoValidate, 2042 NgControlStatus, 2043 NgControlStatusGroup, 2044 NgModel, 2045 ReactiveFormsModule, 2046 FormGroupDirective, 2047 FormControlName, 2048 NgIcon, 2049 TranslateModule, 2050 TranslatePipe, 2051 IonHeader, 2052 IonToolbar, 2053 IonButtons, 2054 IonMenuButton, 2055 IonTitle, 2056 IonContent, 2057 IonInput, 2058 IonToggle, 2059 IonFab, 2060 IonFabButton, 2061 IonSelect, 2062 IonSelectOption, 2063 IonCard, 2064 IonCardContent, 2065 IonCardHeader, 2066 IonCardTitle, 2067 IonButton, 2068 IonChip 2069], styles: ['\n\n.settings-container[_ngcontent-%COMP%] {\n min-height: 100%;\n background: var(--ion-background-color);\n padding-bottom: 80px;\n}\n.settings-section[_ngcontent-%COMP%] {\n margin-bottom: 2rem;\n}\n.settings-section[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 1rem;\n padding: 1.5rem 1rem 1rem;\n background: var(--ion-background-color);\n}\n.section-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n flex: 1;\n margin: 0;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--ion-text-color);\n letter-spacing: -0.02em;\n}\n.section-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background:\n linear-gradient(\n 135deg,\n rgba(var(--ion-color-primary-rgb), 0.1) 0%,\n rgba(var(--ion-color-primary-rgb), 0.05) 100%);\n border-radius: 12px;\n}\n.section-icon[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n color: var(--ion-color-primary);\n}\n.section-icon.bluetooth[_ngcontent-%COMP%] {\n background:\n linear-gradient(\n 135deg,\n rgba(59, 130, 246, 0.1) 0%,\n rgba(59, 130, 246, 0.05) 100%);\n}\n.section-icon.bluetooth[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n color: #3b82f6;\n}\n.section-icon.grid[_ngcontent-%COMP%] {\n background:\n linear-gradient(\n 135deg,\n rgba(139, 92, 246, 0.1) 0%,\n rgba(139, 92, 246, 0.05) 100%);\n}\n.section-icon.grid[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n color: #8b5cf6;\n}\n.section-icon.signal[_ngcontent-%COMP%] {\n background:\n linear-gradient(\n 135deg,\n rgba(236, 72, 153, 0.1) 0%,\n rgba(236, 72, 153, 0.05) 100%);\n}\n.section-icon.signal[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n color: #ec4899;\n}\n.section-icon.advanced[_ngcontent-%COMP%] {\n background:\n linear-gradient(\n 135deg,\n rgba(6, 182, 212, 0.1) 0%,\n rgba(6, 182, 212, 0.05) 100%);\n}\n.section-icon.advanced[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n color: #06b6d4;\n}\n.section-icon.kalman[_ngcontent-%COMP%] {\n background:\n linear-gradient(\n 135deg,\n rgba(34, 197, 94, 0.1) 0%,\n rgba(34, 197, 94, 0.05) 100%);\n}\n.section-icon.kalman[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n color: #22c55e;\n}\n.section-icon.navigation[_ngcontent-%COMP%] {\n background:\n linear-gradient(\n 135deg,\n rgba(5, 150, 105, 0.1) 0%,\n rgba(5, 150, 105, 0.05) 100%);\n}\n.section-icon.navigation[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n color: #059669;\n}\n.section-icon.animation[_ngcontent-%COMP%] {\n background:\n linear-gradient(\n 135deg,\n rgba(245, 158, 11, 0.1) 0%,\n rgba(245, 158, 11, 0.05) 100%);\n}\n.section-icon.animation[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n color: #f59e0b;\n}\n.section-icon.easter-egg[_ngcontent-%COMP%] {\n background:\n linear-gradient(\n 135deg,\n rgba(232, 153, 199, 0.1) 0%,\n rgba(221, 180, 212, 0.05) 100%);\n}\n.section-icon.easter-egg[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n background:\n linear-gradient(\n 135deg,\n #e899c7 0%,\n #d67ba8 100%);\n background-clip: text;\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n}\n.section-icon.signal-processing[_ngcontent-%COMP%] {\n background:\n linear-gradient(\n 135deg,\n rgba(34, 197, 94, 0.1) 0%,\n rgba(34, 197, 94, 0.05) 100%);\n}\n.section-icon.signal-processing[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n color: #22c55e;\n}\n.section-icon.advanced[_ngcontent-%COMP%] {\n background:\n linear-gradient(\n 135deg,\n rgba(6, 182, 212, 0.1
2069) 0%,\n rgba(6, 182, 212, 0.05) 100%);\n}\n.section-icon.advanced[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n color: #06b6d4;\n}\n.section-icon.appearance[_ngcontent-%COMP%] {\n background:\n linear-gradient(\n 135deg,\n rgba(217, 70, 239, 0.1) 0%,\n rgba(217, 70, 239, 0.05) 100%);\n}\n.section-icon.appearance[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n color: #d946ef;\n}\n.settings-list[_ngcontent-%COMP%] {\n padding: 0 1rem;\n}\n.setting-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 1rem;\n margin-bottom: 0.75rem;\n padding: 1rem;\n background: var(--ion-item-background);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n transition: all 0.2s ease;\n min-height: 80px;\n}\n.setting-item[_ngcontent-%COMP%]:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px var(--shadow-color);\n background: var(--ion-color-step-100);\n}\n.setting-item[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n.setting-item.toggle-item[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n.setting-divider[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 1.5rem 0 1rem;\n position: relative;\n}\n.setting-divider[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n position: relative;\n z-index: 1;\n background: var(--ion-background-color, var(--ion-card-background, #f6f8fc));\n padding: 0 1rem;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--ion-color-medium);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n.setting-divider[_ngcontent-%COMP%]::before {\n content: "";\n position: absolute;\n top: 50%;\n left: 0;\n right: 0;\n height: 1px;\n background:\n linear-gradient(\n 90deg,\n transparent,\n var(--ion-color-light),\n transparent);\n z-index: 0;\n}\n.setting-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 1rem;\n flex: 1;\n}\n.setting-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.setting-actions[_ngcontent-%COMP%] ion-button[_ngcontent-%COMP%] {\n --padding-start: 8px;\n --padding-end: 8px;\n height: 36px;\n min-width: 36px;\n}\n.setting-icon[_ngcontent-%COMP%] {\n width: 44px;\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n background:\n linear-gradient(\n 135deg,\n rgba(var(--ion-color-medium-rgb), 0.1) 0%,\n rgba(var(--ion-color-medium-rgb), 0.05) 100%);\n border-radius: 10px;\n flex-shrink: 0;\n}\n.setting-icon[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n color: var(--ion-color-medium);\n}\n.setting-details[_ngcontent-%COMP%] {\n flex: 1;\n}\n.setting-details[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 0.25rem;\n font-size: 1rem;\n font-weight: 600;\n color: var(--ion-text-color);\n letter-spacing: -0.01em;\n}\n.setting-details[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 0.875rem;\n color: var(--ion-color-medium);\n line-height: 1.4;\n}\n.custom-input[_ngcontent-%COMP%] {\n --background: var(--ion-color-step-150);\n --color: var(--ion-text-color);\n --padding-start: 12px;\n --padding-end: 12px;\n --padding-top: 10px;\n --padding-bottom: 10px;\n --border-radius: 8px;\n max-width: 120px;\n text-align: right;\n font-weight: 500;\n border: 1px solid var(--border-color-light);\n transition: all 0.2s ease;\n}\n.custom-input[_ngcontent-%COMP%]:hover {\n --background: var(--ion-color-step-200);\n border-color: var(--border-color);\n}\n.custom-input.ion-focused[_ngcontent-%COMP%] {\n --background: var(--ion-color-step-100);\n border-color: var(--ion-color-primary);\n box-shadow: 0 0 0 3px rgba(var(--ion-color-primary-rgb), 0.1);\n}\n.custom-input.ion-valid[_ngcontent-%COMP%] {\n --color: var(--ion-text-color);\n}\n.custom-input.ion-invalid.ion-touched[_ngcontent-%COMP%] {\n border-color: #ef4444;\n --color: $error-color;\n}\n.custom-select[_ngcontent-%COMP%] {\n --color: var(--ion-text-color);\n --padding-start: 12px;\n --padding-end: 12px;\n --padding-top: 10px;\n --padding-bottom: 10px;\n background: var(--ion-color-step-150);\n border-radius: 8px;\n max-width: 200px;\n font-weight: 500;\n border: 1px solid var(--border-color-light);\n transition: all 0.2s ease;\n}\n.custom-select[_ngcontent-%COMP%]:hover {\n background: var(--ion-color-step-200);\n border-color: var(--border-color);\n}\n.custom-select.ion-focused[_ngcontent-%COMP%] {\n background: var(--ion-color-step-100);\n border-color: var(--ion-color-primary);\n box-shadow: 0 0 0 3px rgba(var(--ion-color-primary-rgb), 0.1);\n}\n.custom-select[_ngcontent-%COMP%]::part(text) {\n text-align: right;\n}\n.custom-select[_ngcontent-%COMP%]::part(icon) {\n color: var(--ion-color-medium);\n opacity: 0.7;\n}\n.master-toggle[_ngcontent-%COMP%] {\n background:\n linear-gradient(\n 135deg,\n rgba(var(--ion-color-primary-rgb), 0.05),\n rgba(var(--ion-color-primary-rgb), 0.02));\n border: 1px solid rgba(var(--ion-color-primary-rgb), 0.1);\n margin-bottom: 0.5rem;\n}\n.master-toggle[_ngcontent-%COMP%] .setting-icon[_ngcontent-%COMP%] {\n background: var(--ion-color-primary);\n}\n.master-toggle[_ngcontent-%COMP%] .setting-icon[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n color: white !important;\n}
2069\n.master-toggle[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--ion-color-primary);\n}\n.divider[_ngcontent-%COMP%] {\n height: 1px;\n background: rgba(var(--ion-color-medium-rgb), 0.2);\n margin: 1rem 1rem 0.5rem;\n}\nion-toggle[_ngcontent-%COMP%] {\n --background: var(--ion-color-medium-tint);\n --background-checked: var(--ion-color-primary);\n --handle-background: white;\n --handle-background-checked: white;\n --handle-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);\n padding: 0;\n}\nion-fab-button[_ngcontent-%COMP%] {\n --background: var(--ion-color-primary);\n --background-hover: var(--ion-color-primary-shade);\n --background-activated: var(--ion-color-primary-tint);\n --box-shadow: 0 4px 16px rgba(var(--ion-color-primary-rgb), 0.4);\n width: 56px;\n height: 56px;\n}\nion-fab-button[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\nion-fab-button[disabled][_ngcontent-%COMP%] {\n --background: var(--ion-color-medium);\n --box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n opacity: 0.5;\n}\nion-fab-button[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n}\n@keyframes _ngcontent-%COMP%_slideIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.settings-section[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_slideIn 0.3s ease-out;\n animation-fill-mode: both;\n}\n.settings-section[_ngcontent-%COMP%]:nth-child(1) {\n animation-delay: 0.1s;\n}\n.settings-section[_ngcontent-%COMP%]:nth-child(2) {\n animation-delay: 0.2s;\n}\n.settings-section[_ngcontent-%COMP%]:nth-child(3) {\n animation-delay: 0.3s;\n}\n.settings-section[_ngcontent-%COMP%]:nth-child(4) {\n animation-delay: 0.4s;\n}\n.settings-section[_ngcontent-%COMP%]:nth-child(5) {\n animation-delay: 0.5s;\n}\n.settings-section[_ngcontent-%COMP%]:nth-child(6) {\n animation-delay: 0.6s;\n}\n.settings-section[_ngcontent-%COMP%]:nth-child(7) {\n animation-delay: 0.7s;\n}\n.settings-section[_ngcontent-%COMP%]:nth-child(8) {\n animation-delay: 0.8s;\n}\n.settings-section[_ngcontent-%COMP%]:nth-child(9) {\n animation-delay: 0.9s;\n}\n.settings-section[_ngcontent-%COMP%]:nth-child(10) {\n animation-delay: 1s;\n}\n@media (max-width: 768px) {\n .settings-container[_ngcontent-%COMP%] {\n padding-bottom: 70px;\n }\n .section-header[_ngcontent-%COMP%] {\n padding: 1rem 0.75rem 0.75rem;\n }\n .section-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 1.1rem;\n }\n .section-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n }\n .section-icon[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n font-size: 1.25em;\n }\n .settings-list[_ngcontent-%COMP%] {\n padding: 0 0.75rem;\n }\n .setting-item[_ngcontent-%COMP%] {\n padding: 0.875rem;\n min-height: 72px;\n }\n .setting-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n }\n .setting-icon[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n font-size: 1.1em;\n }\n .setting-details[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n font-size: 0.95rem;\n }\n .setting-details[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 0.8125rem;\n }\n .custom-input[_ngcontent-%COMP%], \n .custom-select[_ngcontent-%COMP%] {\n max-width: 100px;\n font-size: 0.9rem;\n }\n ion-fab-button[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n }\n ion-fab-button[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n }\n}\n@media (prefers-color-scheme: dark) {\n .setting-item[_ngcontent-%COMP%] {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n }\n .setting-item[_ngcontent-%COMP%]:hover {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n }\n}\n@keyframes _ngcontent-%COMP%_successPulse {\n 0% {\n transform: scale(1);\n box-shadow: 0 4px 16px rgba(var(--ion-color-primary-rgb), 0.4);\n }\n 50% {\n transform: scale(1.1);\n box-shadow: 0 6px 24px rgba(var(--ion-color-primary-rgb), 0.6);\n }\n 100% {\n transform: scale(1);\n box-shadow: 0 4px 16px rgba(var(--ion-color-primary-rgb), 0.4);\n }\n}\n.save-success[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_successPulse 0.5s ease-out;\n}\n.device-info-card[_ngcontent-%COMP%] {\n margin: 1rem;\n border-radius: 16px;\n background: var(--ion-card-background);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n}\n.device-info-card[_ngcontent-%COMP%] ion-card-header[_ngcontent-%COMP%] {\n padding: 1rem;\n}\n.device-info-card[_ngcontent-%COMP%] ion-card-title[_ngcontent-%COMP%] {\n font-size: 1.1rem;\n}\n.device-info-card[_ngcontent-%COMP%] .device-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.device-info-card[_ngcontent-%COMP%] .device-header[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n color: var(--ion-color-primary);\n}\n.device-info-card[_ngcontent-%COMP%] .device-header[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n flex: 1;\n}\n.device-info-card[_ngcontent-%COMP%] .device-header[_ngcontent-%COMP%] ion-button[_ngcontent-%COMP%] {\n --padding-start: 0.5rem;\n --padding-end: 0.5rem;\n}\n.device-info-card[_ngcontent-%COMP%] ion-card-content[_ngcontent-%COMP%] {\n padding: 0 1rem 1rem;\n}\n.device-info-card[_ngcontent-%COMP%] .device-info-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 1rem;\n margin-bottom: 1rem;\n}\n.device-info-card[_ngcontent-%COMP%] .device-info-grid[_ngcontent-%COMP%] .info-item[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n font-size: 0.875rem;\n color: var(--ion-color-medium);\n margin-bottom: 0.25rem;\n}\n.device-info-card[_ngcontent-%COMP%] .device-info-grid[_ngcontent-%COMP%] .info-item[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: block;\n font-size: 1rem;\n color: var(--ion-text-color);\n font-weight: 500;\n}\n.device-info-card[_ngcontent-%COMP%] .device-info-grid[_ngcontent-%COMP%] .warning-chip[_ngcontent-%COMP%], \n.device-info-card[_ngcontent-%COMP%] .device-info-grid[_ngcontent-%COMP%] .info-chip[_ngcontent-%COMP%] {\n grid-column: 1/-1;\n margin-top: 0.5rem;\n}\n.device-info-card[_ngcontent-%COMP%] .device-info-grid[_ngcontent-%COMP%] .warning-chip[_ngcontent-%COMP%] ion-chip[_ngcontent-%COMP%], \n.device-info-card[_ngcontent-%COMP%] .device-info-grid[_ngcontent-%COMP%] .info-chip[_ngcontent-%COMP%] ion-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n}\n.device-info-card[_ngcontent-%COMP%] .device-info-grid[_ngcontent-%COMP%] .warning-chip[_ngcontent-%COMP%] ion-chip[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%], \n.device-info-card[_ngcontent-%COMP%] .device-info-grid[_ngcontent-%COMP%] .info-chip[_ngcontent-%COMP%] ion-chip[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n flex-shrink: 0;\n}\n.device-info-card[_ngcontent-%COMP%] .device-actions[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end;\n padding-top: 0.5rem;\n border-top: 1px solid var(--ion-color-light);\n}\n.device-info-card[_ngcontent-%COMP%] .device-actions[_ngcontent-%COMP%] ion-button[_ngcontent-%COMP%] {\n --padding-start: 1rem;\n --padding-end: 1rem;\n}\n.device-info-card[_ngcontent-%COMP%] .device-actions[_ngcontent-%COMP%] ion-button[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n margin-right: 0.5rem;\n}\n.persistent-position-selector[_ngcontent-%COMP%] {\n align-items: center;\n}\n.persistent-position-selector[_ngcontent-%COMP%] ion-select[_ngcontent-%COMP%] {\n min-width: min(240px, 42vw);\n}\n.persistent-position-summary[_ngcontent-%COMP%], \n.persistent-position-message[_ngcontent-%COMP%] {\n margin: 0 0 0.75rem;\n padding: 0.875rem 1rem;\n border-radius: 10px;\n background: rgba(var(--ion-color-primary-rgb), 0.08);\n color: var(--ion-text-color);\n}\n.persistent-position-summary[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n.persistent-position-summary[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n color: var(--ion-color-medium);\n font-size: 0.875rem;\n}\n.persistent-position-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 0.5rem;\n font-size: 0.875rem;\n line-height: 1.4;\n}\n.persistent-position-message[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n flex-shrink: 0;\n margin-top: 0.1rem;\n}\n.persistent-position-message.warning-message[_ngcontent-%COMP%] {\n background: rgba(var(--ion-color-warning-rgb), 0.12);\n color: var(--ion-color-warning-shade);\n}\n.log-file-item[_ngcontent-%COMP%] .setting-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n.log-file-item[_ngcontent-%COMP%] .log-file-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n flex-shrink: 0;\n margin-left: 1rem;\n}\n.log-file-item[_ngcontent-%COMP%] .log-file-actions[_ngcontent-%COMP%] ion-button[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n --padding-start: 0;\n --padding-end: 0;\n}\n.log-file-item[_ngcontent-%COMP%] .log-file-actions[_ngcontent-%COMP%] ion-button[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n font-size: 1em;\n}\n.log-file-item[_ngcontent-%COMP%] .setting-details[_ngcontent-%COMP%] h4[_ng
2069content-%COMP%] {\n font-size: 0.9rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.log-file-item[_ngcontent-%COMP%] .setting-details[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 0.8rem;\n color: var(--ion-color-medium);\n}\n.section-icon.debug[_ngcontent-%COMP%] {\n background:\n linear-gradient(\n 135deg,\n #dc2626,\n #b91c1c);\n color: white;\n}\n.setting-item.session-info[_ngcontent-%COMP%] {\n border-left: 4px solid var(--ion-color-success);\n background: rgba(var(--ion-color-success-rgb), 0.05);\n}\n.setting-item.session-info[_ngcontent-%COMP%] .setting-details[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-family: "Courier New", monospace;\n font-size: 0.85rem;\n margin: 0.25rem 0;\n}\n@media (max-width: 768px) {\n .persistent-position-selector[_ngcontent-%COMP%] {\n align-items: stretch;\n flex-direction: column;\n }\n .persistent-position-selector[_ngcontent-%COMP%] ion-select[_ngcontent-%COMP%] {\n width: 100%;\n min-width: 0;\n }\n .log-file-item[_ngcontent-%COMP%] .log-file-actions[_ngcontent-%COMP%] {\n margin-left: 0.5rem;\n }\n .log-file-item[_ngcontent-%COMP%] .log-file-actions[_ngcontent-%COMP%] ion-button[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n }\n .log-file-item[_ngcontent-%COMP%] .log-file-actions[_ngcontent-%COMP%] ion-button[_ngcontent-%COMP%] ng-icon[_ngcontent-%COMP%] {\n font-size: 0.9em;\n }\n}'] }); 2070var SettingsPage = _SettingsPage; 2071(() => { 2072 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(SettingsPage, [{ 2073 type: Component, 2074 args: [{ selector: "app-settings", imports: [ 2075 FormsModule, 2076 ReactiveFormsModule, 2077 NgIcon, 2078 TranslateModule, 2079 IonHeader, 2080 IonToolbar, 2081 IonButtons, 2082 IonMenuButton, 2083 IonTitle, 2084 IonContent, 2085 IonInput, 2086 IonToggle, 2087 IonFab, 2088 IonFabButton, 2089 IonSelect, 2090 IonSelectOption, 2091 IonCard, 2092 IonCardContent, 2093 IonCardHeader, 2094 IonCardTitle, 2095 IonButton, 2096 IonChip 2097 ], viewProviders: [provideIcons({ 2098 lucideSave, 2099 lucideSettings2, 2100 lucideMenu, 2101 lucideBug, 2102 lucideBluetooth, 2103 lucideActivity, 2104 lucideTag, 2105 lucideGrid3x3, 2106 lucideToggleLeft, 2107 lucideEye, 2108 lucideRuler, 2109 lucideRadar, 2110 lucideOctagon, 2111 lucideTrendingUp, 2112 lucideTrendingDown, 2113 lucideTimer, 2114 lucideRefreshCw, 2115 lucideRotateCw, 2116 lucideZap, 2117 lucideTarget, 2118 lucideHistory, 2119 lucideFilter, 2120 lucideWaves, 2121 lucideSignalLow, 2122 lucideSignalHigh, 2123 lucideChartLine, 2124 lucideTimerOff, 2125 lucideNavigation2, 2126 lucideCircleDot, 2127 lucideMapPin, 2128 lucideRoute, 2129 lucideSparkles, 2130 lucidePalette, 2131 lucideRainbow, 2132 lucideBrain, 2133 lucideMove, 2134 lucideGauge, 2135 lucideCircle, 2136 lucideMonitor, 2137 lucideHand, 2138 lucidePaintbrush, 2139 lucideDroplets, 2140 lucideCpu, 2141 lucideRadio, 2142 lucideNavigation, 2143 lucideMoveHorizontal, 2144 lucideLayers, 2145 lucideArrowUpDown, 2146 lucideBell, 2147 lucideMousePointer, 2148 lucideChevronUp, 2149 lucideChevronDown, 2150 lucideTriangleAlert, 2151 lucideInfo, 2152 lucideUsers, 2153 lucideGitBranchPlus, 2154 lucideSettings, 2155 lucideClock, 2156 lucideGlobe, 2157 lucidePlay, 2158 lucideSquare, 2159 lucideDownload, 2160 lucideFileText, 2161 lucideTrash2, 2162 lucideFile, 2163 lucideShare, 2164 lucideSmartphone, 2165 lucideLock, 2166 lucideMagnet, 2167 lucideSatellite, 2168 lucideBuilding2, 2169 lucideRouteIcon: lucideRoute, 2170 lucideSlidersHorizontal, 2171 lucideSun, 2172 lucideVolume2 2173 })], template: `<ion-header [translucent]="true"> 2174 <ion-toolbar> 2175 <ion-buttons slot="start"> 2176 <ion-menu-button></ion-menu-button> 2177 </ion-buttons> 2178 <ion-title>{{ 'settings.title' | translate }}</ion-title> 2179 </ion-toolbar> 2180</ion-header> 2181 2182<ion-content [fullscreen]="true"> 2183 <div class="settings-container"> 2184 <form [formGroup]="settingsForm" (ngSubmit)="confirm()"> 2185 2186 <!-- User Preferences Section --> 2187 <div class="settings-section"> 2188 <div class="section-header"> 2189 <div class="section-icon"> 2190 <ng-icon name="lucideGlobe" size="1.5em"></ng-icon> 2191 </div> 2192 <h3>{{ 'settings.userPreferences.title' | translate }}</h3> 2193 </div> 2194 2195 <div class="settings-list"> 2196 <!-- Language --> 2197 <div class="setting-item"> 2198 <div class="setting-content"> 2199 <div class="setting-icon"> 2200 <ng-icon name="lucideGlobe" size="1.3em"></ng-icon> 2201 </div> 2202 <div class="setting-details"> 2203 <h4>{{ 'language.selector.subtitle' | translate }}</h4> 2204 <p>{{ 'settings.choose.language' | translate }}</p> 2205 </div> 2206 </div> 2207 <ion-select 2208 [value]="selectedLanguage" 2209 (ionChange)="onLanguageChange($event.detail.value)" 2210 interface="popover" 2211 mode="ios" 2212 class="custom-select" 2213 > 2214 <ion-select-option value="lv">Latvie\u0161u (Latvian)</ion-select-option> 2215 <ion-select-option value="en">English (English)</ion-select-option> 2216 <ion-select-option value="de">
2216Deutsch (German)</ion-select-option> 2217 <ion-select-option value="ru">\u0420\u0443\u0441\u0441\u043A\u0438\u0439 (Russian)</ion-select-option> 2218 </ion-select> 2219 </div> 2220 2221 <!-- Map Rotation --> 2222 <div class="setting-item"> 2223 <div class="setting-content"> 2224 <div class="setting-icon"> 2225 <ng-icon name="lucideRotateCw" size="1.3em"></ng-icon> 2226 </div> 2227 <div class="setting-details"> 2228 <h4>{{ 'settings.navigation.rotation.title' | translate }}</h4> 2229 <p>{{ 'settings.navigation.rotation.description' | translate }}</p> 2230 </div> 2231 </div> 2232 <ion-select 2233 formControlName="mapRotationMode" 2234 [selectedText]="mapRotationModeLabel" 2235 interface="popover" 2236 mode="ios" 2237 class="custom-select" 2238 > 2239 <ion-select-option value="heading">{{ 'settings.navigation.rotation.heading.title' | translate }}</ion-select-option> 2240 <ion-select-option value="north">{{ 'settings.navigation.rotation.north.title' | translate }}</ion-select-option> 2241 </ion-select> 2242 </div> 2243 2244 <!-- Voice Navigation --> 2245 <div class="setting-item toggle-item"> 2246 <div class="setting-content"> 2247 <div class="setting-icon"> 2248 <ng-icon name="lucideVolume2" size="1.3em"></ng-icon> 2249 </div> 2250 <div class="setting-details"> 2251 <h4>{{ 'navigation.voice.enabled.title' | translate }}</h4> 2252 <p>{{ 'navigation.voice.enabled.description' | translate }}</p> 2253 </div> 2254 </div> 2255 <ion-toggle formControlName="voiceNavigationEnabled" mode="ios"></ion-toggle> 2256 </div> 2257 2258 <!-- Keep Screen Awake --> 2259 <div class="setting-item toggle-item"> 2260 <div class="setting-content"> 2261 <div class="setting-icon"> 2262 <ng-icon name="lucideSmartphone" size="1.3em"></ng-icon> 2263 </div> 2264 <div class="setting-details"> 2265 <h4>{{ 'settings.navigation.keepScreenAwake.title' | translate }}</h4> 2266 <p>{{ 'settings.navigation.keepScreenAwake.description' | translate }}</p> 2267 </div> 2268 </div> 2269 <ion-toggle formControlName="keepScreenAwakeDuringNavigation" mode="ios"></ion-toggle> 2270 </div> 2271 2272 <!-- Display Divider (Admin) --> 2273 @if (isAdmin) { 2274 <div class="setting-divider"> 2275 <span>{{ 'settings.display.title' | translate }}</span> 2276 </div> 2277 } 2278 2279 <!-- Rendering Mode --> 2280 <div class="setting-item"> 2281 <div class="setting-content"> 2282 <div class="setting-icon"> 2283 <ng-icon name="lucideLayers" size="1.3em"></ng-icon> 2284 </div> 2285 <div class="setting-details"> 2286 <h4>{{ 'settings.renderingMode.title' | translate }}</h4> 2287 <p>{{ 'settings.renderingMode.description' | translate }}</p> 2288 </div> 2289 </div> 2290 <ion-select 2291 formControlName="renderingMode" 2292 [selectedText]="renderingModeLabel" 2293 interface="popover" 2294 mode="ios" 2295 class="custom-select" 2296 > 2297 <ion-select-option value="auto">{{ 'settings.renderingMode.options.auto' | translate }}</ion-select-option> 2298 <ion-select-option value="2d">{{ 'settings.renderingMode.options.2d' | translate }}</ion-select-option> 2299 <ion-select-option value="3d">{{ 'settings.renderingMode.options.3d' | translate }}</ion-select-option> 2300 </ion-select> 2301 </div> 2302 2303 <!-- OpenMaps Basemap --> 2304 <div class="setting-item toggle-item"> 2305 <div class="setting-content"> 2306 <div class="setting-icon"> 2307 <ng-icon name="lucideGlobe" size="1.3em"></ng-icon> 2308 </div> 2309 <div class="setting-details"> 2310 <h4>{{ 'settings.openMaps.title' | translate }}</h4> 2311 <p>{{ 'settings.openMaps.description' | translate }}</p> 2312 </div> 2313 </div> 2314 <ion-toggle formControlName="openMapsEnabled" mode="ios"></ion-toggle> 2315 </div> 2316 2317 <!-- Auto-Center Countdown --> 2318 <div class="setting-item toggle-item"> 2319 <div class="setting-content"> 2320 <div class="setting-icon"> 2321 <ng-icon name="lucideTimer" size="1.3em"></ng-icon> 2322 </div> 2323 <div class="setting-details"> 2324 <h4>{{ 'settings.navigation.autoCenter.title' | translate }}</h4> 2325 <p>{{ 'settings.navigation.autoCenter.description' | translate }}</p> 2326 </div> 2327 </div> 2328 <ion-toggle formControlName="enableAutoCenterCountdown" mode="ios"></ion-toggle> 2329 </div> 2330 2331 <!-- Navigation View Tuning Controls --> 2332 <div class="setting-item toggle-item"> 2333 <div class="setting-content"> 2334 <div class="setting-icon"> 2335 <ng-icon name="lucideSlidersHorizontal" size="1.3em"></ng-icon> 2336 </div> 2337 <div class="setting-details"> 2338 <h4>{{ 'settings.navigation.viewTuning.title' | translate }}</h4> 2339 <p>{{ 'settings.navigation.viewTuning.description' | translate }}</p> 2340 </div> 2341 </div> 2342 <ion-toggle formControlName="showNavigationViewTuningControls" mode="ios"></ion-toggle> 2343 </div> 2344 2345 <!-- Navigation Surface Projection --> 2346 <div class="setting-item toggle-item"> 2347 <div class="setting-content"> 2348 <div class="setting-icon"> 2349 <ng-icon name="lucideLayers" size="1.3em"></ng-icon> 2350 </div> 2351 <div class="setting-details"> 2352 <h4>{{ 'settings.navigation.surfaceProjection.title' | translate }}</h4> 2353 <p>{{ 'settings.navigation.surfaceProjection.description' | translate }}</p> 2354 </div> 2355 </div> 2356 <ion-toggle formControlName="navigationSurfaceProjectionEnabled" mode="ios"></ion-toggle> 2357 </div> 2358 2359 <!-- Navigation Lighting Tuning Controls --> 2360 <div class="setting-item toggle-item"> 2361 <div class="setting-content"> 2362 <div class="setting-icon"> 2363 <ng-icon name="lucideSun" size="1.3em"></ng-icon> 2364 </div> 2365 <div class="setting-details"> 2366 <h4>{{ 'settings.navigation.lightingTuning.title' | translate }}</h4> 2367 <p>{{ 'settings.navigation.lightingTuning.description' | translate }}</p> 2368 </div> 2369 </div> 2370 <ion-toggle formControlName="showNavigationLightingTuningControls" mode="ios"></ion-toggle> 2371 </div> 2372 2373 <!-- Campus 3D Model Tuning Controls --> 2374 <div class="setting-item toggle-item"> 2375 <div class="setting-content"> 2376 <div class="setting-icon"> 2377 <ng-icon name="lucideMove" size="1.3em"></ng-icon> 2378 </div> 2379 <div class="setting-details"> 2380 <h4>{{ 'settings.navigation.modelTuning.title' | translate }}</h4> 2381 <p>{{ 'settings.navigation.modelTuning.description' | translate }}</p> 2382 </div> 2383 </div> 2384 <ion-toggle formControlName="showNavigationModelTuningControls" mode="ios"></ion-toggle> 2385 </div> 2386 </div> 2387 </div> 2388 2389 <!-- Navigation & Positioning Section --> 2390 <div class="settings-section"> 2391 <div class="section-header"> 2392 <div class="section-icon"> 2393 <ng-icon name="lucideNavigation2" size="1.5em"></ng-icon> 2394 </div> 2395 <h3>{{ 'settings.navigationSection.title' | translate }}</h3> 2396 </div> 2397 2398 <div class="settings-list"> 2399 <!-- Positioning Mode --> 2400 <div class="setting-item toggle-item"> 2401 <div class="setting-content"> 2402 <div class="setting-icon"> 2403 <ng-icon name="lucideActivity" size="1.3em"></ng-icon> 2404 </div> 2405 <div class="setting-details"> 2406 <h4>
2406{{ 'settings.navigationSection.responsivePositioning.title' | translate }}</h4> 2407 <p>{{ 'settings.navigationSection.responsivePositioning.description' | translate }}</p> 2408 </div> 2409 </div> 2410 <ion-toggle formControlName="positioningModeResponsive" mode="ios" (ionChange)="onPositioningModeChange()"></ion-toggle> 2411 </div> 2412 2413 <!-- Smart Source Switching (Admin) --> 2414 @if (isAdmin) { 2415 <div class="setting-item toggle-item"> 2416 <div class="setting-content"> 2417 <div class="setting-icon"> 2418 <ng-icon name="lucideTarget" size="1.3em"></ng-icon> 2419 </div> 2420 <div class="setting-details"> 2421 <h4>{{ 'settings.navigationSection.smartSourceSwitching.title' | translate }}</h4> 2422 <p>{{ 'settings.navigationSection.smartSourceSwitching.description' | translate }}</p> 2423 </div> 2424 </div> 2425 <ion-toggle formControlName="enableSmartSourceSwitching" mode="ios"></ion-toggle> 2426 </div> 2427 2428 <!-- Segment Hysteresis --> 2429 <div class="setting-item toggle-item"> 2430 <div class="setting-content"> 2431 <div class="setting-icon"> 2432 <ng-icon name="lucideRoute" size="1.3em"></ng-icon> 2433 </div> 2434 <div class="setting-details"> 2435 <h4>{{ 'settings.enable_segment_hysteresis' | translate }}</h4> 2436 <p>{{ 'settings.enable_segment_hysteresis_desc' | translate }}</p> 2437 </div> 2438 </div> 2439 <ion-toggle formControlName="enableSegmentHysteresis" mode="ios"></ion-toggle> 2440 </div> 2441 2442 @if (settingsForm.get('enableSegmentHysteresis')?.value) { 2443 <div class="setting-item"> 2444 <div class="setting-content"> 2445 <div class="setting-icon"> 2446 <ng-icon name="lucideRuler" size="1.3em"></ng-icon> 2447 </div> 2448 <div class="setting-details"> 2449 <h4>{{ 'settings.segment_hysteresis_threshold' | translate }}</h4> 2450 <p>{{ 'settings.segment_hysteresis_threshold_desc' | translate }}</p> 2451 </div> 2452 </div> 2453 <ion-input 2454 formControlName="segmentHysteresisThreshold" 2455 type="number" 2456 min="50" 2457 max="500" 2458 step="50" 2459 class="custom-input"> 2460 </ion-input> 2461 </div> 2462 } 2463 2464 <!-- Force Dual Mode --> 2465 <div class="setting-item toggle-item"> 2466 <div class="setting-content"> 2467 <div class="setting-icon"> 2468 <ng-icon name="lucideSatellite" size="1.3em"></ng-icon> 2469 </div> 2470 <div class="setting-details"> 2471 <h4>{{ 'settings.navigationSection.forceDualMode.title' | translate }}</h4> 2472 <p>{{ 'settings.navigationSection.forceDualMode.description' | translate }}</p> 2473 </div> 2474 </div> 2475 <ion-toggle formControlName="forceDualMode" mode="ios"></ion-toggle> 2476 </div> 2477 2478 <!-- Force Beacon Only --> 2479 <div class="setting-item toggle-item"> 2480 <div class="setting-content"> 2481 <div class="setting-icon"> 2482 <ng-icon name="lucideRadio" size="1.3em"></ng-icon> 2483 </div> 2484 <div class="setting-details"> 2485 <h4>{{ 'settings.navigationSection.forceBeaconOnly.title' | translate }}</h4> 2486 <p>{{ 'settings.navigationSection.forceBeaconOnly.description' | translate }}</p> 2487 </div> 2488 </div> 2489 <ion-toggle formControlName="forceBeaconOnlyMode" mode="ios"></ion-toggle> 2490 </div> 2491 } 2492 </div> 2493 </div> 2494 2495 <!-- Signal Processing Section (Admin Only) --> 2496 @if (isAdmin) { 2497 <div class="settings-section"> 2498 <div class="section-header"> 2499 <div class="section-icon signal-processing"> 2500 <ng-icon name="lucideActivity" size="1.5em"></ng-icon> 2501 </div> 2502 <h3>
2502{{ 'settings.signalProcessing.title' | translate }}</h3> 2503 <p>{{ 'settings.signalProcessing.description' | translate }}</p> 2504 </div> 2505 2506 <div class="settings-list"> 2507 <!-- RSSI Filter Type --> 2508 <div class="setting-item"> 2509 <div class="setting-content"> 2510 <div class="setting-icon"> 2511 <ng-icon name="lucideFilter" size="1.3em"></ng-icon> 2512 </div> 2513 <div class="setting-details"> 2514 <h4>{{ 'settings.rssiFilter.filterType.title' | translate }}</h4> 2515 <p>{{ 'settings.rssiFilter.filterType.description' | translate }}</p> 2516 </div> 2517 </div> 2518 <ion-select 2519 formControlName="rssiFilterType" 2520 [selectedText]="rssiFilterTypeLabel" 2521 interface="popover" 2522 mode="ios" 2523 class="custom-select" 2524 > 2525 <ion-select-option value="none">{{ 'settings.rssiFilter.options.none' | translate }}</ion-select-option> 2526 <ion-select-option value="kalman">{{ 'settings.rssiFilter.options.kalman' | translate }}</ion-select-option> 2527 <ion-select-option value="adaptiveEma">{{ 'settings.rssiFilter.options.adaptiveEma' | translate }}</ion-select-option> 2528 <ion-select-option value="simpleEma">{{ 'settings.rssiFilter.options.simpleEma' | translate }}</ion-select-option> 2529 <ion-select-option value="simpleSma">{{ 'settings.rssiFilter.options.simpleSma' | translate }}</ion-select-option> 2530 </ion-select> 2531 </div> 2532 2533 <!-- Kalman Filter Parameters --> 2534 @if (settingsForm.get('rssiFilterType')?.value === 'kalman') { 2535 <div class="filter-parameters"> 2536 <div class="setting-item"> 2537 <div class="setting-content"> 2538 <div class="setting-icon"> 2539 <ng-icon name="lucideActivity" size="1.3em"></ng-icon> 2540 </div> 2541 <div class="setting-details"> 2542 <h4>{{ 'settings.rssiFilter.kalman.processNoise.title' | translate }}</h4> 2543 <p>{{ 'settings.rssiFilter.kalman.processNoise.description' | translate }}</p> 2544 </div> 2545 </div> 2546 <ion-input 2547 formControlName="kalmanProcessNoise" 2548 type="number" 2549 step="0.1" 2550 placeholder="1.0" 2551 class="custom-input"> 2552 </ion-input> 2553 </div> 2554 2555 <div class="setting-item"> 2556 <div class="setting-content"> 2557 <div class="setting-icon"> 2558 <ng-icon name="lucideRadar" size="1.3em"></ng-icon> 2559 </div> 2560 <div class="setting-details"> 2561 <h4>{{ 'settings.rssiFilter.kalman.measurementNoise.title' | translate }}</h4> 2562 <p>{{ 'settings.rssiFilter.kalman.measurementNoise.description' | translate }}</p> 2563 </div> 2564 </div> 2565 <ion-input 2566 formControlName="kalmanMeasurementNoise" 2567 type="number" 2568 step="0.1" 2569 placeholder="4.0" 2570 class="custom-input"> 2571 </ion-input> 2572 </div> 2573 2574 <div class="setting-item"> 2575 <div class="setting-content"> 2576 <div class="setting-icon"> 2577 <ng-icon name="lucideTarget" size="1.3em"></ng-icon> 2578 </div> 2579 <div class="setting-details"> 2580 <h4>{{ 'settings.rssiFilter.kalman.estimationError.title' | translate }}</h4> 2581 <p>{{ 'settings.rssiFilter.kalman.estimationError.description' | translate }}</p> 2582 </div> 2583 </div> 2584 <ion-input 2585 formControlName="kalmanEstimationError" 2586 type="number" 2587 step="0.1" 2588 placeholder="1.0" 2589 class="custom-input"> 2590 </ion-input> 2591 </div> 2592 </div> 2593 } 2594 2595 <!-- Adaptive EMA Parameters --> 2596 @if (settingsForm.get('rssiFilterType')?.value === 'adaptiveEma') { 2597 <div class="filter-parameters"> 2598 <div class="setting-item"> 2599 <div class="setting-content"> 2600 <div class="setting-icon"> 2601 <ng-icon name="lucideGauge" size="1.3em"></ng-icon> 2602 </div> 2603 <div class="setting-details"> 2604 <h4>{{ 'settings.rssiFilter.ema.baseAlpha.title' | translate }}</h4> 2605 <p>{{ 'settings.rssiFilter.ema.baseAlpha.description' | translate }}</p> 2606 </div> 2607 </div> 2608 <ion-input 2609 formControlName="adaptiveEmaBaseAlpha" 2610 type="number" 2611 step="0.01" 2612 min="0.01" 2613 max="1.0" 2614 placeholder="0.3" 2615 class="custom-input"> 2616 </ion-input> 2617 </div> 2618 2619 <div class="setting-item"> 2620 <div class="setting-content"> 2621 <div class="setting-icon"> 2622 <ng-icon name="lucideTriangleAlert" size="1.3em"></ng-icon> 2623 </div> 2624 <div class="setting-details"> 2625 <h4>{{ 'settings.rssiFilter.ema.outlierThreshold.title' | translate }}</h4> 2626 <p>{{ 'settings.rssiFilter.ema.outlierThreshold.description' | translate }}</p> 2627 </div> 2628 </div> 2629 <ion-input 2630 formControlName="adaptiveEmaOutlierThreshold" 2631 type="number" 2632 step="0.1" 2633 min="1.0" 2634 max="5.0" 2635 placeholder="2.5" 2636 class="custom-input"> 2637 </ion-input> 2638 </div> 2639 </div> 2640 } 2641 2642 <!-- Simple EMA Parameters --> 2643 @if (settingsForm.get('rssiFilterType')?.value === 'simpleEma') { 2644 <div class="filter-parameters"> 2645 <div class="setting-item"> 2646 <div class="setting-content"> 2647 <div class="setting-icon"> 2648 <ng-icon name="lucideGauge" size="1.3em"></ng-icon> 2649 </div> 2650 <div class="setting-details"> 2651 <h4>{{ 'settings.rssiFilter.ema.alpha.title' | translate }}</h4> 2652 <p>{{ 'settings.rssiFilter.ema.alpha.description' | translate }}</p> 2653 </div> 2654 </div> 2655 <ion-input 2656 formControlName="simpleEmaAlpha" 2657 type="number" 2658 step="0.01" 2659 min="0.01" 2660 max="1.0" 2661 placeholder="0.35" 2662 class="custom-input"> 2663 </ion-input> 2664 </div> 2665 2666 <div class="setting-item"> 2667 <div class="setting-content"> 2668 <div class="setting-icon"> 2669 <ng-icon name="lucideTriangleAlert" size="1.3em"></ng-icon> 2670 </div> 2671 <div class="setting-details"> 2672 <h4>{{ 'settings.rssiFilter.ema.outlierThreshold.title' | translate }}</h4> 2673 <p>{{ 'settings.rssiFilter.ema.outlierThreshold.description' | translate }}</p> 2674 </div> 2675 </div> 2676 <ion-input 2677 formControlName="simpleEmaOutlierThreshold" 2678 type="number" 2679 step="0.1" 2680 min="1.0" 2681 max="5.0" 2682 placeholder="2.5" 2683 class="custom-input"> 2684 </ion-input> 2685 </div> 2686 </div> 2687 } 2688 2689 <!-- Graph-Constrained Kalman Filter --> 2690 <div class="setting-divider">
2691 <span>{{ 'settings.signalProcessing.kalmanFilter' | translate }}</span> 2692 </div> 2693 2694 <div class="setting-item toggle-item"> 2695 <div class="setting-content"> 2696 <div class="setting-icon"> 2697 <ng-icon name="lucideTrendingUp" size="1.3em"></ng-icon> 2698 </div> 2699 <div class="setting-details"> 2700 <h4>{{ 'settings.positionKalman.enable.title' | translate }}</h4> 2701 <p>{{ 'settings.positionKalman.enable.description' | translate }}</p> 2702 </div> 2703 </div> 2704 <ion-toggle formControlName="enableGraphKalmanFilter" mode="ios"></ion-toggle> 2705 </div> 2706 2707 @if (settingsForm.get('enableGraphKalmanFilter')?.value) { 2708 <div class="setting-item"> 2709 <div class="setting-content"> 2710 <div class="setting-icon"> 2711 <ng-icon name="lucideZap" size="1.3em"></ng-icon> 2712 </div> 2713 <div class="setting-details"> 2714 <h4>{{ 'settings.positionKalman.maxVelocity.title' | translate }}</h4> 2715 <p>{{ 'settings.positionKalman.maxVelocity.description' | translate }}</p> 2716 </div> 2717 </div> 2718 <ion-input 2719 formControlName="kalmanMaxVelocity" 2720 type="number" 2721 min="50" 2722 max="500" 2723 step="10" 2724 placeholder="200" 2725 class="custom-input"> 2726 </ion-input> 2727 </div> 2728 2729 <div class="setting-item"> 2730 <div class="setting-content"> 2731 <div class="setting-icon"> 2732 <ng-icon name="lucideTrendingDown" size="1.3em"></ng-icon> 2733 </div> 2734 <div class="setting-details"> 2735 <h4>{{ 'settings.positionKalman.velocityDecay.title' | translate }}</h4> 2736 <p>{{ 'settings.positionKalman.velocityDecay.description' | translate }}</p> 2737 </div> 2738 </div> 2739 <ion-input 2740 formControlName="kalmanVelocityDecay" 2741 type="number" 2742 step="0.01" 2743 min="0.8" 2744 max="1.0" 2745 placeholder="0.95" 2746 class="custom-input"> 2747 </ion-input> 2748 </div> 2749 2750 <div class="setting-item"> 2751 <div class="setting-content"> 2752 <div class="setting-icon"> 2753 <ng-icon name="lucideMagnet" size="1.3em"></ng-icon> 2754 </div> 2755 <div class="setting-details"> 2756 <h4>{{ 'settings.positionKalman.pathSnapDistance.title' | translate }}</h4> 2757 <p>{{ 'settings.positionKalman.pathSnapDistance.description' | translate }}</p> 2758 </div> 2759 </div> 2760 <ion-input 2761 formControlName="kalmanPathSnapThreshold" 2762 type="number" 2763 min="10" 2764 max="300" 2765 step="10" 2766 placeholder="100" 2767 class="custom-input"> 2768 </ion-input> 2769 </div> 2770 } 2771 </div> 2772 </div> 2773 } 2774 2775 <!-- Performance & Device Section --> 2776 <div class="settings-section"> 2777 <div class="section-header"> 2778 <div class="section-icon"> 2779 <ng-icon name="lucideCpu" size="1.5em"></ng-icon> 2780 </div> 2781 <h3>{{ 'settings.performance.title' | translate }}</h3> 2782 </div> 2783 2784 <!-- Device Info Card --> 2785 @if (deviceCapabilities) { 2786 <ion-card class="device-info-card"> 2787 <ion-card-header> 2788 <ion-card-title> 2789 <div class="device-header"> 2790 <ng-icon name="lucideCpu" size="1.3em"></ng-icon> 2791 <span>{{ 'settings.performance.deviceInfo.title' | translate }}</span>
2792 <ion-button fill="clear" size="small" (click)="toggleDeviceInfo()"> 2793 <ng-icon [name]="showDeviceInfo ? 'lucideChevronUp' : 'lucideChevronDown'" size="1.2em"></ng-icon> 2794 </ion-button> 2795 </div> 2796 </ion-card-title> 2797 </ion-card-header> 2798 @if (showDeviceInfo) { 2799 <ion-card-content> 2800 <div class="device-info-grid"> 2801 <div class="info-item"> 2802 <label>{{ 'settings.performance.deviceInfo.deviceModel' | translate }}</label> 2803 <span>{{ deviceCapabilities.deviceModel || ('settings.performance.deviceInfo.unknown' | translate) }}</span> 2804 </div> 2805 <div class="info-item"> 2806 <label>{{ 'settings.performance.deviceInfo.gpu' | translate }}</label> 2807 <span>{{ deviceCapabilities.gpuRenderer || ('settings.performance.deviceInfo.unknown' | translate) }}</span> 2808 </div> 2809 <div class="info-item"> 2810 <label>{{ 'settings.performance.deviceInfo.webglVersion' | translate }}</label> 2811 <span>{{ deviceCapabilities.webglVersion || ('settings.performance.deviceInfo.notSupported' | translate) }}</span> 2812 </div> 2813 <div class="info-item"> 2814 <label>{{ 'settings.performance.deviceInfo.maxTextureSize' | translate }}</label> 2815 <span>{{ deviceCapabilities.maxTextureSize }}px</span> 2816 </div> 2817 @if (deviceCapabilities.hasKnownFlickeringIssue) { 2818 <div class="warning-chip"> 2819 <ion-chip color="warning"> 2820 <ng-icon name="lucideTriangleAlert" size="1em"></ng-icon> 2821 <span>{{ 'settings.performance.deviceInfo.flickeringWarning' | translate }}</span> 2822 </ion-chip> 2823 </div> 2824 } 2825 @if (deviceCapabilities.isLowEndDevice) { 2826 <div class="info-chip"> 2827 <ion-chip color="medium"> 2828 <ng-icon name="lucideInfo" size="1em"></ng-icon> 2829 <span>{{ 'settings.performance.deviceInfo.lowEndWarning' | translate }}</span> 2830 </ion-chip> 2831 </div> 2832 } 2833 </div> 2834 <div class="device-actions"> 2835 <ion-button size="small" fill="outline" (click)="resetDeviceDetection()"> 2836 <ng-icon name="lucideRefreshCw" size="1em"></ng-icon> 2837 <span>{{ 'settings.performance.deviceInfo.redetect' | translate }}</span> 2838 </ion-button> 2839 @if (deviceCapabilities.hasKnownFlickeringIssue || showReportButton) { 2840 <ion-button size="small" fill="outline" color="warning" (click)="reportFlickering()"> 2841 <ng-icon name="lucideTriangleAlert" size="1em"></ng-icon> 2842 <span>{{ 'settings.performance.deviceInfo.reportIssue' | translate }}</span> 2843 </ion-button> 2844 } 2845 </div> 2846 </ion-card-content> 2847 } 2848 </ion-card> 2849 } 2850 2851 </div> 2852 2853 <!-- Advanced Settings Section (Admin Only) --> 2854 @if (isAdmin) { 2855 <div class="settings-section"> 2856 <div class="section-header"> 2857 <div class="section-icon advanced"> 2858 <ng-icon name="lucideSettings" size="1.5em"></ng-icon> 2859 </div> 2860 <h3>{{ 'settings.advanced.title' | translate }}</h3> 2861 </div> 2862 2863 <div class="settings-list"> 2864 <!-- Backend Configuration --> 2865 @if (showApiUrlSection) { 2866 <div class="setting-item"> 2867 <div class="setting-content"> 2868 <div class="setting-icon"> 2869 <ng-icon name="lucideSatellite" size="1.3em"></ng-icon> 2870 </div> 2871 <div class="setting-details"> 2872 <h4>{{ 'settings.backend.server' | translate }}</h4> 2873 <p>{{ 'settings.backend.current' | translate }}: {{ currentApiUrlName }}</p> 2874 @if (isProduction) { 2875 <p class="warning-text"> 2876 <ng-icon name="lucideTriangleAlert" size="0.9em"></ng-icon> 2877 {{ 'settings.backend.warning' | translate }} 2878 </p> 2879 } 2880 </div> 2881 </div> 2882 <ion-select 2883 [(ngModel)]="selectedApiUrl" 2884 [ngModelOptions]="{standalone: true}" 2885 (ionChange)="onApiUrlChange()" 2886 interface="action-sheet" 2887 mode="ios" 2888 class="custom-select" 2889 > 2890 @for (urlOption of availableApiUrls; track urlOption.url) { 2891 <ion-select-option [value]="urlOption.url"> 2892 {{ urlOption.name }} 2893 </ion-select-option> 2894 } 2895 </ion-select> 2896 </div> 2897 } 2898 2899 <!-- Bluetooth Settings --> 2900 <div class="setting-item"> 2901 <div class="setting-content"> 2902 <div class="setting-icon"> 2903 <ng-icon name="lucideBluetooth" size="1.3em"></ng-icon> 2904 </div> 2905 <div class="setting-details"> 2906 <h4>{{ 'settings.bluetooth.scanMode.title' | translate }}</h4> 2907 <p>{{ 'settings.bluetooth.scanMode.description' | translate }}</p> 2908 </div> 2909 </div> 2910 <ion-select formControlName="bleScanMode" [selectedText]="bleScanModeLabel" interface="popover" mode="ios" class="custom-select"> 2911 <ion-select-option value="low_latency">{{ 'settings.bluetooth.scanModeOptions.lowLatency' | translate }}</ion-select-option> 2912 <ion-select-option value="balanced">{{ 'settings.bluetooth.scanModeOptions.balanced' | translate }}</ion-select-option> 2913 <ion-select-option value="low_power">{{ 'settings.bluetooth.scanModeOptions.lowPower' | translate }}</ion-select-option> 2914 </ion-select> 2915 </div> 2916 2917 <div class="setting-item"> 2918 <div class="setting-content"> 2919 <div class="setting-icon"> 2920 <ng-icon name="lucideTag" size="1.3em"></ng-icon> 2921 </div> 2922 <div class="setting-details"> 2923 <h4>{{ 'settings.bluetooth.tagPrefix.title' | translate }}</h4> 2924 <p>{{ 'settings.bluetooth.tagPrefix.description' | translate }}</p> 2925 </div> 2926 </div> 2927 <ion-input 2928 formControlName="tagAllowedPrefix" 2929 type="text" 2930 placeholder="e.g., KBPro" 2931 class="custom-input"> 2932 </ion-input> 2933 </div> 2934 2935 <div class="setting-divider">
2936 <span>{{ 'settings.advanced.debug' | translate }}</span> 2937 </div> 2938 2939 <div class="setting-item toggle-item persistent-position-toggle"> 2940 <div class="setting-content"> 2941 <div class="setting-icon"> 2942 <ng-icon name="lucideMapPin" size="1.3em"></ng-icon> 2943 </div> 2944 <div class="setting-details"> 2945 <h4>{{ 'settings.persistentPosition.title' | translate }}</h4> 2946 <p>{{ 'settings.persistentPosition.description' | translate }}</p> 2947 </div> 2948 </div> 2949 <ion-toggle 2950 formControlName="persistentPositionEnabled" 2951 mode="ios" 2952 [disabled]="!persistentPositionCanBeEnabled"> 2953 </ion-toggle> 2954 </div> 2955 2956 @if (debugPositionPresets.length > 0 || hasMissingPersistentPreset) { 2957 <div class="setting-item persistent-position-selector"> 2958 <div class="setting-content"> 2959 <div class="setting-icon"> 2960 <ng-icon name="lucideTarget" size="1.3em"></ng-icon> 2961 </div> 2962 <div class="setting-details"> 2963 <h4>{{ 'settings.persistentPosition.preset' | translate }}</h4> 2964 <p>{{ 'settings.persistentPosition.presetDescription' | translate }}</p> 2965 </div> 2966 </div> 2967 <ion-select 2968 formControlName="persistentPositionPresetId" 2969 interface="popover" 2970 mode="ios" 2971 class="custom-select" 2972 [placeholder]="'settings.persistentPosition.selectPreset' | translate"> 2973 @for (preset of debugPositionPresets; track preset.id) { 2974 <ion-select-option [value]="preset.id">{{ preset.name }}</ion-select-option> 2975 } 2976 </ion-select> 2977 </div> 2978 } @else { 2979 <div class="persistent-position-message info-message"> 2980 <ng-icon name="lucideInfo" size="1em"></ng-icon> 2981 <span>{{ 'settings.persistentPosition.noPresets' | translate }}</span> 2982 </div> 2983 } 2984 2985 @if (selectedPersistentPositionPreset; as preset) { 2986 <div class="persistent-position-summary"> 2987 <strong>{{ preset.name }}</strong> 2988 <span>{{ getPersistentPresetContext(preset) }}</span> 2989 <span> 2990 X: {{ preset.x }} cm \xB7 Y: {{ preset.y }} cm \xB7 2991 {{ 'settings.persistentPosition.sourceLabel' | translate }}: 2992 {{ getPersistentPresetSource(preset) }} 2993 </span> 2994 </div> 2995 } 2996 2997 @if (hasMissingPersistentPreset || debugPositionOverrideState.persistentValidity === 'missing-preset') { 2998 <div class="persistent-position-message warning-message"> 2999 <ng-icon name="lucideTriangleAlert" size="1em"></ng-icon> 3000 <span>{{ 'settings.persistentPosition.missingPreset' | translate }}</span> 3001 </div> 3002 } @else if (debugPositionOverrideState.persistentValidity === 'missing-context') { 3003 <div class="persistent-position-message warning-message"> 3004 <ng-icon name="lucideTriangleAlert" size="1em"></ng-icon> 3005 <span>{{ 'settings.persistentPosition.missingContext' | translate }}</span> 3006 </div> 3007 } @else if (debugPositionOverrideState.persistentValidity === 'pending') { 3008 <div class="persistent-position-message info-message"> 3009 <ng-icon name="lucideInfo" size="1em"></ng-icon> 3010 <span>{{ 'settings.persistentPosition.pending' | translate }}</span> 3011 </div> 3012 } 3013 3014 @if (debugPositionOverrideState.origin === 'temporary' && debugPositionOverrideState.persistentConfig.enabled) { 3015 <div class="persistent-position-message info-message"> 3016 <ng-icon name="lucideInfo" size="1em"></ng-icon>
3017 <span>{{ 'settings.persistentPosition.temporaryPriority' | translate }}</span> 3018 </div> 3019 } 3020 3021 <div class="setting-item toggle-item"> 3022 <div class="setting-content"> 3023 <div class="setting-icon"> 3024 <ng-icon name="lucideRotateCw" size="1.3em"></ng-icon> 3025 </div> 3026 <div class="setting-details"> 3027 <h4>{{ 'settings.navigationSection.dynamicRotation.title' | translate }}</h4> 3028 <p>{{ 'settings.navigationSection.dynamicRotation.description' | translate }}</p> 3029 </div> 3030 </div> 3031 <ion-toggle formControlName="enableDynamicRotationSync" mode="ios"></ion-toggle> 3032 </div> 3033 3034 <div class="setting-item toggle-item"> 3035 <div class="setting-content"> 3036 <div class="setting-icon"> 3037 <ng-icon name="lucideBug" size="1.3em"></ng-icon> 3038 </div> 3039 <div class="setting-details"> 3040 <h4>{{ 'settings.navigationSection.beaconDebugLogging.title' | translate }}</h4> 3041 <p>{{ 'settings.navigationSection.beaconDebugLogging.description' | translate }}</p> 3042 </div> 3043 </div> 3044 <ion-toggle formControlName="enableBeaconDebugLogging" mode="ios"></ion-toggle> 3045 </div> 3046 3047 <div class="setting-item toggle-item"> 3048 <div class="setting-content"> 3049 <div class="setting-icon"> 3050 <ng-icon name="lucideBell" size="1.3em"></ng-icon> 3051 </div> 3052 <div class="setting-details"> 3053 <h4>{{ 'settings.signal.recorder.panel' | translate }}</h4> 3054 <p>{{ 'settings.signal.recorder.panel.description' | translate }}</p> 3055 </div> 3056 </div> 3057 <ion-toggle formControlName="showSignalRecorderPanel" mode="ios"></ion-toggle> 3058 </div> 3059 3060 <div class="setting-item toggle-item"> 3061 <div class="setting-content"> 3062 <div class="setting-icon"> 3063 <ng-icon name="lucideRadio" size="1.3em"></ng-icon> 3064 </div> 3065 <div class="setting-details"> 3066 <h4>{{ 'settings.navigation.clampGpsOutside.title' | translate }}</h4> 3067 <p>{{ 'settings.navigation.clampGpsOutside.description' | translate }}</p> 3068 </div> 3069 </div> 3070 <ion-toggle formControlName="clampGpsOutsideBuildings" mode="ios"></ion-toggle> 3071 </div> 3072 </div> 3073 </div> 3074 } 3075 3076 <!-- Appearance Section (Admin Only) --> 3077 @if (isAdmin) { 3078 <div class="settings-section"> 3079 <div class="section-header"> 3080 <div class="section-icon appearance"> 3081 <ng-icon name="lucidePalette" size="1.5em"></ng-icon> 3082 </div> 3083 <h3>{{ 'settings.appearance.title' | translate }}</h3> 3084 </div> 3085 3086 <div class="settings-list"> 3087 <!-- Grid Settings --> 3088 <div class="setting-item toggle-item"> 3089 <div class="setting-content"> 3090 <div class="setting-icon"> 3091 <ng-icon name="lucideGrid3x3" size="1.3em"></ng-icon> 3092 </div> 3093 <div class="setting-details"> 3094 <h4>{{ 'settings.grid.enable.title' | translate }}</h4> 3095 <p>{{ 'settings.grid.enable.description' | translate }}</p> 3096 </div> 3097 </div> 3098 <ion-toggle formControlName="gridEnabled" mode="ios"></ion-toggle> 3099 </div> 3100 3101 <div class="setting-item toggle-item"> 3102 <div class="setting-content"> 3103 <div class="setting-icon"> 3104 <ng-icon name="lucideEye" size="1.3em"></ng-icon> 3105 </div> 3106 <div class="setting-details"> 3107 <h4>{{ 'settings.grid.show.title' | translate }}</h4> 3108 <p>{{ 'settings.grid.show.description' | translate }}</p> 3109 </div> 3110 </div> 3111 <ion-toggle formControlName="gridVisible" mode="ios"></ion-toggle> 3112 </div> 3113 3114 <div class="setting-item"> 3115 <div class="setting-content"> 3116 <div class="setting-icon"> 3117 <ng-icon name="lucideRuler" size="1.3em"></ng-icon> 3118 </div> 3119 <div class="setting-details"> 3120 <h4>{{ 'settings.grid.size.title' | translate }}</h4> 3121 <p>{{ 'settings.grid.size.description' | translate }}</p> 3122 </div> 3123 </div> 3124 <ion-input 3125 formControlName="gridSize" 3126 type="number" 3127 placeholder="100" 3128 class="custom-input"> 3129 </ion-input> 3130 </div> 3131 3132 <div class="setting-divider">
3133 <span>{{ 'settings.theme.title' | translate }}</span> 3134 </div> 3135 3136 <div class="setting-item toggle-item"> 3137 <div class="setting-content"> 3138 <div class="setting-icon"> 3139 <ng-icon name="lucidePalette" size="1.3em"></ng-icon> 3140 </div> 3141 <div class="setting-details"> 3142 <h4>{{ 'settings.theme.pink.title' | translate }}</h4> 3143 <p>{{ 'settings.theme.pink.description' | translate }}</p> 3144 </div> 3145 </div> 3146 <ion-toggle formControlName="enablePinkTheme" mode="ios"></ion-toggle> 3147 </div> 3148 3149 <div class="setting-item toggle-item"> 3150 <div class="setting-content"> 3151 <div class="setting-icon"> 3152 <ng-icon name="lucideRainbow" size="1.3em"></ng-icon> 3153 </div> 3154 <div class="setting-details"> 3155 <h4>{{ 'settings.theme.rainbow.title' | translate }}</h4> 3156 <p>{{ 'settings.theme.rainbow.description' | translate }}</p> 3157 </div> 3158 </div> 3159 <ion-toggle formControlName="enableRainbowTheme" mode="ios"></ion-toggle> 3160 </div> 3161 </div> 3162 </div> 3163 } 3164 3165 <!-- Experimental Section (Admin Only) --> 3166 @if (isAdmin) { 3167 <div class="settings-section experimental-section"> 3168 <div class="section-header"> 3169 <div class="section-icon experimental"> 3170 <ng-icon name="lucideTriangleAlert" size="1.5em"></ng-icon> 3171 </div> 3172 <h3>{{ 'settings.experimental.title' | translate }}</h3> 3173 <ion-chip color="warning" class="experimental-chip"> 3174 <ng-icon name="lucideTriangleAlert" size="0.9em"></ng-icon> 3175 <span>{{ 'settings.experimental.chip' | translate }}</span> 3176 </ion-chip> 3177 </div> 3178 3179 <div class="settings-list"> 3180 <div class="setting-item toggle-item"> 3181 <div class="setting-content"> 3182 <div class="setting-icon"> 3183 <ng-icon name="lucideLayers" size="1.3em"></ng-icon> 3184 </div> 3185 <div class="setting-details"> 3186 <h4>{{ 'settings.experimental.buildingOutlines.title' | translate }}</h4> 3187 <p>{{ 'settings.experimental.buildingOutlines.description' | translate }}</p> 3188 </div> 3189 </div> 3190 <ion-toggle formControlName="enableBuildingOutlineMerging" mode="ios"></ion-toggle> 3191 </div> 3192 </div> 3193 </div> 3194 } 3195 3196 </form> 3197 </div> 3198</ion-content> 3199 3200<!-- Floating Save Button --> 3201<ion-fab slot="fixed" vertical="bottom" horizontal="end"> 3202 <ion-fab-button [disabled]="!settingsForm.valid" (click)="confirm()"> 3203 <ng-icon name="lucideSave" size="1.5em" /> 3204 </ion-fab-button> 3205</ion-fab> 3206`, styles: ['/* src/app/pages/settings/settings.page.scss */\n.settings-container {\n min-height: 100%;\n background: var(--ion-background-color);\n padding-bottom: 80px;\n}\n.settings-section {\n margin-bottom: 2rem;\n}\n.settings-section:last-child {\n margin-bottom: 0;\n}\n.section-header {\n display: flex;\n align-items: center;\n gap: 1rem;\n padding: 1.5rem 1rem 1rem;\n background: var(--ion-background-color);\n}\n.section-header h3 {\n flex: 1;\n margin: 0;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--ion-text-color);\n letter-spacing: -0.02em;\n}\n.section-icon {\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n background:\n linear-gradient(\n 135deg,\n rgba(var(--ion-color-primary-rgb), 0.1) 0%,\n rgba(var(--ion-color-primary-rgb), 0.05) 100%);\n border-radius: 12px;\n}\n.section-icon ng-icon {\n color: var(--ion-color-primary);\n}\n.section-icon.bluetooth {\n background:\n linear-gradient(\n 135deg,\n rgba(59, 130, 246, 0.1) 0%,\n rgba(59, 130, 246, 0.05) 100%);\n}\n.section-icon.bluetooth ng-icon {\n color: #3b82f6;\n}\n.section-icon.grid {\n background:\n linear-gradient(\n 135deg,\n rgba(139, 92, 246, 0.1) 0%,\n rgba(139, 92, 246, 0.05) 100%);\n}\n.section-icon.grid ng-icon {\n color: #8b5cf6;\n}\n.section-icon.signal {\n background:\n linear-gradient(\n 135deg,\n rgba(236, 72, 153, 0.1) 0%,\n rgba(236, 72, 153, 0.05) 100%);\n}\n.section-icon.signal ng-icon {\n color: #ec4899;
3206\n}\n.section-icon.advanced {\n background:\n linear-gradient(\n 135deg,\n rgba(6, 182, 212, 0.1) 0%,\n rgba(6, 182, 212, 0.05) 100%);\n}\n.section-icon.advanced ng-icon {\n color: #06b6d4;\n}\n.section-icon.kalman {\n background:\n linear-gradient(\n 135deg,\n rgba(34, 197, 94, 0.1) 0%,\n rgba(34, 197, 94, 0.05) 100%);\n}\n.section-icon.kalman ng-icon {\n color: #22c55e;\n}\n.section-icon.navigation {\n background:\n linear-gradient(\n 135deg,\n rgba(5, 150, 105, 0.1) 0%,\n rgba(5, 150, 105, 0.05) 100%);\n}\n.section-icon.navigation ng-icon {\n color: #059669;\n}\n.section-icon.animation {\n background:\n linear-gradient(\n 135deg,\n rgba(245, 158, 11, 0.1) 0%,\n rgba(245, 158, 11, 0.05) 100%);\n}\n.section-icon.animation ng-icon {\n color: #f59e0b;\n}\n.section-icon.easter-egg {\n background:\n linear-gradient(\n 135deg,\n rgba(232, 153, 199, 0.1) 0%,\n rgba(221, 180, 212, 0.05) 100%);\n}\n.section-icon.easter-egg ng-icon {\n background:\n linear-gradient(\n 135deg,\n #e899c7 0%,\n #d67ba8 100%);\n background-clip: text;\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n}\n.section-icon.signal-processing {\n background:\n linear-gradient(\n 135deg,\n rgba(34, 197, 94, 0.1) 0%,\n rgba(34, 197, 94, 0.05) 100%);\n}\n.section-icon.signal-processing ng-icon {\n color: #22c55e;\n}\n.section-icon.advanced {\n background:\n linear-gradient(\n 135deg,\n rgba(6, 182, 212, 0.1) 0%,\n rgba(6, 182, 212, 0.05) 100%);\n}\n.section-icon.advanced ng-icon {\n color: #06b6d4;\n}\n.section-icon.appearance {\n background:\n linear-gradient(\n 135deg,\n rgba(217, 70, 239, 0.1) 0%,\n rgba(217, 70, 239, 0.05) 100%);\n}\n.section-icon.appearance ng-icon {\n color: #d946ef;\n}\n.settings-list {\n padding: 0 1rem;\n}\n.setting-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 1rem;\n margin-bottom: 0.75rem;\n padding: 1rem;\n background: var(--ion-item-background);\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n transition: all 0.2s ease;\n min-height: 80px;\n}\n.setting-item:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px var(--shadow-color);\n background: var(--ion-color-step-100);\n}\n.setting-item:last-child {\n margin-bottom: 0;\n}\n.setting-item.toggle-item {\n cursor: pointer;\n}\n.setting-divider {\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 1.5rem 0 1rem;\n position: relative;\n}\n.setting-divider span {\n position: relative;\n z-index: 1;\n background: var(--ion-background-color, var(--ion-card-background, #f6f8fc));\n padding: 0 1rem;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--ion-color-medium);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n.setting-divider::before {\n content: "";\n position: absolute;\n top: 50%;\n left: 0;\n right: 0;\n height: 1px;\n background:\n linear-gradient(\n 90deg,\n transparent,\n var(--ion-color-light),\n transparent);\n z-index: 0;\n}\n.setting-content {\n display: flex;\n align-items: center;\n gap: 1rem;\n flex: 1;\n}\n.setting-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.setting-actions ion-button {\n --padding-start: 8px;\n --padding-end: 8px;\n height: 36px;\n min-width: 36px;\n}\n.setting-icon {\n width: 44px;\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n background:\n linear-gradient(\n 135deg,\n rgba(var(--ion-color-medium-rgb), 0.1) 0%,\n rgba(var(--ion-color-medium-rgb), 0.05) 100%);\n border-radius: 10px;\n flex-shrink: 0;\n}\n.setting-icon ng-icon {\n color: var(--ion-color-medium);\n}\n.setting-details {\n flex: 1;\n}\n.setting-details h4 {\n margin: 0 0 0.25rem;\n font-size: 1rem;\n font-weight: 600;\n color: var(--ion-text-color);\n letter-spacing: -0.01em;\n}\n.setting-details p {\n margin: 0;\n font-size: 0.875rem;\n color: var(--ion-color-medium);\n line-height: 1.4;\n}\n.custom-input {\n --background: var(--ion-color-step-150);\n --color: var(--ion-text-color);\n --padding-start: 12px;\n --padding-end: 12px;\n --padding-top: 10px;\n --padding-bottom: 10px;\n --border-radius: 8px;\n max-width: 120px;\n text-align: right;\n font-weight: 500;\n border: 1px solid var(--border-color-light);\n transition: all 0.2s ease;\n}\n.custom-input:hover {\n --background: var(--ion-color-step-200);\n border-color: var(--border-color);\n}\n.custom-input.ion-focused {\n --background: var(--ion-color-step-100);\n border-color: var(--ion-color-primary);\n box-shadow: 0 0 0 3px rgba(var(--ion-color-primary-rgb), 0.1);\n}\n.custom-input.ion-valid {\n --color: var(--ion-text-color);\n}\n.custom-input.ion-invalid.ion-touched {\n border-color: #ef4444;\n --color: $error-color;\n}\n.custom-select {\n --color: var(--ion-text-color);\n --padding-start: 12px;\n --padding-end: 12px;\n --padding-top: 10px;\n --padding-bottom: 10px;\n background: var(--ion-color-step-150);\n border-radius: 8px;\n max-width: 200px;\n font-weight: 500;\n border: 1px solid var(--border-color-light);\n transition: all 0.2s ease;\n}\n.custom-select:hover {\n background: var(--ion-color-step-200);\n border-color: var(--border-color);\n}\n.custom-select.ion-focused {\n background: var(--ion-color-step-100);\n border-color: var(--ion-color-primary);\n box-shadow: 0 0 0 3px rgba(var(--ion-color-primary-rgb), 0.1);\n}\n.custom-select::part(text) {\n text-align: right;\n}\n.custom-select::part(icon) {\n color: var(--ion-color-medium);\n opacity: 0.7;\n}\n.master-toggle {\n background:\n linear-gradient(\n 135deg,\n rgba(var(--ion-color-primary-rgb), 0.05),\n rgba(var(--ion-color-primary-rgb), 0.02));\n border: 1px solid rgba(var(--ion-color-primary-rgb), 0.1);\n margin-bottom: 0.5rem;\n}\n.master-toggle .setting-icon {\n background: var(--ion-color-primary);\n}\n.master-toggle .setting-icon ng-icon {\n color: white !important;\n}\n.master-toggle h4 {\n font-weight: 600;\n color: var(--ion-color-primary);\n}\n.divider {\n height: 1px;\n background: rgba(var(--ion-color-medium-rgb), 0.2);\n margin: 1rem 1rem 0.5rem;\n}\nion-toggle {\n --background: var(--ion-color-medium-tint);\n --background-checked: var(--ion-color-primary);\n --handle-background: white;\n --handle-background-checked: white;\n --handle-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);\n padding: 0;\n}\nion-fab-button {\n --background: var(--ion-color-primary);\n --background-hover: var(--ion-color-primary-shade);\n --background-activated: var(--ion-color-primary-tint);
3206\n --box-shadow: 0 4px 16px rgba(var(--ion-color-primary-rgb), 0.4);\n width: 56px;\n height: 56px;\n}\nion-fab-button:hover {\n transform: scale(1.05);\n}\nion-fab-button[disabled] {\n --background: var(--ion-color-medium);\n --box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n opacity: 0.5;\n}\nion-fab-button ng-icon {\n font-size: 1.5rem;\n}\n@keyframes slideIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.settings-section {\n animation: slideIn 0.3s ease-out;\n animation-fill-mode: both;\n}\n.settings-section:nth-child(1) {\n animation-delay: 0.1s;\n}\n.settings-section:nth-child(2) {\n animation-delay: 0.2s;\n}\n.settings-section:nth-child(3) {\n animation-delay: 0.3s;\n}\n.settings-section:nth-child(4) {\n animation-delay: 0.4s;\n}\n.settings-section:nth-child(5) {\n animation-delay: 0.5s;\n}\n.settings-section:nth-child(6) {\n animation-delay: 0.6s;\n}\n.settings-section:nth-child(7) {\n animation-delay: 0.7s;\n}\n.settings-section:nth-child(8) {\n animation-delay: 0.8s;\n}\n.settings-section:nth-child(9) {\n animation-delay: 0.9s;\n}\n.settings-section:nth-child(10) {\n animation-delay: 1s;\n}\n@media (max-width: 768px) {\n .settings-container {\n padding-bottom: 70px;\n }\n .section-header {\n padding: 1rem 0.75rem 0.75rem;\n }\n .section-header h3 {\n font-size: 1.1rem;\n }\n .section-icon {\n width: 40px;\n height: 40px;\n }\n .section-icon ng-icon {\n font-size: 1.25em;\n }\n .settings-list {\n padding: 0 0.75rem;\n }\n .setting-item {\n padding: 0.875rem;\n min-height: 72px;\n }\n .setting-icon {\n width: 36px;\n height: 36px;\n }\n .setting-icon ng-icon {\n font-size: 1.1em;\n }\n .setting-details h4 {\n font-size: 0.95rem;\n }\n .setting-details p {\n font-size: 0.8125rem;\n }\n .custom-input,\n .custom-select {\n max-width: 100px;\n font-size: 0.9rem;\n }\n ion-fab-button {\n width: 48px;\n height: 48px;\n }\n ion-fab-button ng-icon {\n font-size: 1.25rem;\n }\n}\n@media (prefers-color-scheme: dark) {\n .setting-item {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n }\n .setting-item:hover {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n }\n}\n@keyframes successPulse {\n 0% {\n transform: scale(1);\n box-shadow: 0 4px 16px rgba(var(--ion-color-primary-rgb), 0.4);\n }\n 50% {\n transform: scale(1.1);\n box-shadow: 0 6px 24px rgba(var(--ion-color-primary-rgb), 0.6);\n }\n 100% {\n transform: scale(1);\n box-shadow: 0 4px 16px rgba(var(--ion-color-primary-rgb), 0.4);\n }\n}\n.save-success {\n animation: successPulse 0.5s ease-out;\n}\n.device-info-card {\n margin: 1rem;\n border-radius: 16px;\n background: var(--ion-card-background);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n}\n.device-info-card ion-card-header {\n padding: 1rem;\n}\n.device-info-card ion-card-title {\n font-size: 1.1rem;\n}\n.device-info-card .device-header {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.device-info-card .device-header ng-icon {\n color: var(--ion-color-primary);\n}\n.device-info-card .device-header span {\n flex: 1;\n}\n.device-info-card .device-header ion-button {\n --padding-start: 0.5rem;\n --padding-end: 0.5rem;\n}\n.device-info-card ion-card-content {\n padding: 0 1rem 1rem;\n}\n.device-info-card .device-info-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 1rem;\n margin-bottom: 1rem;\n}\n.device-info-card .device-info-grid .info-item label {\n display: block;\n font-size: 0.875rem;\n color: var(--ion-color-medium);\n margin-bottom: 0.25rem;\n}\n.device-info-card .device-info-grid .info-item span {\n display: block;\n font-size: 1rem;\n color: var(--ion-text-color);\n font-weight: 500;\n}\n.device-info-card .device-info-grid .warning-chip,\n.device-info-card .device-info-grid .info-chip {\n grid-column: 1/-1;\n margin-top: 0.5rem;\n}\n.device-info-card .device-info-grid .warning-chip ion-chip,\n.device-info-card .device-info-grid .info-chip ion-chip {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n}\n.device-info-card .device-info-grid .warning-chip ion-chip ng-icon,\n.device-info-card .device-info-grid .info-chip ion-chip ng-icon {\n flex-shrink: 0;\n}\n.device-info-card .device-actions {\n display: flex;\n justify-content: flex-end;\n padding-top: 0.5rem;\n border-top: 1px solid var(--ion-color-light);\n}\n.device-info-card .device-actions ion-button {\n --padding-start: 1rem;\n --padding-end: 1rem;\n}
3206\n.device-info-card .device-actions ion-button ng-icon {\n margin-right: 0.5rem;\n}\n.persistent-position-selector {\n align-items: center;\n}\n.persistent-position-selector ion-select {\n min-width: min(240px, 42vw);\n}\n.persistent-position-summary,\n.persistent-position-message {\n margin: 0 0 0.75rem;\n padding: 0.875rem 1rem;\n border-radius: 10px;\n background: rgba(var(--ion-color-primary-rgb), 0.08);\n color: var(--ion-text-color);\n}\n.persistent-position-summary {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n.persistent-position-summary span {\n color: var(--ion-color-medium);\n font-size: 0.875rem;\n}\n.persistent-position-message {\n display: flex;\n align-items: flex-start;\n gap: 0.5rem;\n font-size: 0.875rem;\n line-height: 1.4;\n}\n.persistent-position-message ng-icon {\n flex-shrink: 0;\n margin-top: 0.1rem;\n}\n.persistent-position-message.warning-message {\n background: rgba(var(--ion-color-warning-rgb), 0.12);\n color: var(--ion-color-warning-shade);\n}\n.log-file-item .setting-content {\n flex: 1;\n min-width: 0;\n}\n.log-file-item .log-file-actions {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n flex-shrink: 0;\n margin-left: 1rem;\n}\n.log-file-item .log-file-actions ion-button {\n width: 32px;\n height: 32px;\n --padding-start: 0;\n --padding-end: 0;\n}\n.log-file-item .log-file-actions ion-button ng-icon {\n font-size: 1em;\n}\n.log-file-item .setting-details h4 {\n font-size: 0.9rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.log-file-item .setting-details p {\n font-size: 0.8rem;\n color: var(--ion-color-medium);\n}\n.section-icon.debug {\n background:\n linear-gradient(\n 135deg,\n #dc2626,\n #b91c1c);\n color: white;\n}\n.setting-item.session-info {\n border-left: 4px solid var(--ion-color-success);\n background: rgba(var(--ion-color-success-rgb), 0.05);\n}\n.setting-item.session-info .setting-details p {\n font-family: "Courier New", monospace;\n font-size: 0.85rem;\n margin: 0.25rem 0;\n}\n@media (max-width: 768px) {\n .persistent-position-selector {\n align-items: stretch;\n flex-direction: column;\n }\n .persistent-position-selector ion-select {\n width: 100%;\n min-width: 0;\n }\n .log-file-item .log-file-actions {\n margin-left: 0.5rem;\n }\n .log-file-item .log-file-actions ion-button {\n width: 28px;\n height: 28px;\n }\n .log-file-item .log-file-actions ion-button ng-icon {\n font-size: 0.9em;\n }\n}\n'] }] 3207 }], () => [{ type: FormBuilder }, { type: SettingsService }, { type: AuthService }, { type: ToastService }, { type: DeviceDetectionService }, { type: LanguageService }, { type: BeaconService }, { type: ApiUrlService }, { type: AlertController }, { type: TranslateService }, { type: DebugControlService }, { type: DatabaseService }], null); 3208})(); 3209(() => { 3210 (typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(SettingsPage, { className: "SettingsPage", filePath: "src/app/pages/settings/settings.page.ts", lineNumber: 76 }); 3211})(); 3212export { 3213 SettingsPage 3214};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.