diff --git a/src/app/components/sleeping-animation-preset-modal/sleeping-animation-preset-modal.component.scss b/src/app/components/sleeping-animation-preset-modal/sleeping-animation-preset-modal.component.scss
index 503f0ca8..05d98f8c 100644
--- a/src/app/components/sleeping-animation-preset-modal/sleeping-animation-preset-modal.component.scss
+++ b/src/app/components/sleeping-animation-preset-modal/sleeping-animation-preset-modal.component.scss
@@ -1,5 +1,3 @@
-
-
.link {
display: flex;
flex-direction: row;
diff --git a/src/app/components/vrchat-login-modal/vrchat-login-modal.component.ts b/src/app/components/vrchat-login-modal/vrchat-login-modal.component.ts
index be460bb4..f2eb36be 100644
--- a/src/app/components/vrchat-login-modal/vrchat-login-modal.component.ts
+++ b/src/app/components/vrchat-login-modal/vrchat-login-modal.component.ts
@@ -53,6 +53,8 @@ export class VRChatLoginModalComponent
this.error = '';
try {
await this.vrchat.login(this.username, this.password);
+ this.loggingIn = false;
+ await this.close();
} catch (e) {
switch (e) {
case '2FA_REQUIRED':
diff --git a/src/app/migrations/app-settings.migrations.ts b/src/app/migrations/app-settings.migrations.ts
index 9af9de44..27923de1 100644
--- a/src/app/migrations/app-settings.migrations.ts
+++ b/src/app/migrations/app-settings.migrations.ts
@@ -1,6 +1,5 @@
import { cloneDeep } from 'lodash';
import { APP_SETTINGS_DEFAULT, AppSettings } from '../models/settings';
-import { AppSettingsService } from '../services/app-settings.service';
import { info } from 'tauri-plugin-log-api';
const migrations: { [v: number]: (data: any) => any } = {
diff --git a/src/app/migrations/telemetry-settings.migrations.ts b/src/app/migrations/telemetry-settings.migrations.ts
index f0188162..38d03b6e 100644
--- a/src/app/migrations/telemetry-settings.migrations.ts
+++ b/src/app/migrations/telemetry-settings.migrations.ts
@@ -1,6 +1,5 @@
import { cloneDeep } from 'lodash';
import { TELEMETRY_SETTINGS_DEFAULT, TelemetrySettings } from '../models/telemetry-settings';
-import { AUTOMATION_CONFIGS_DEFAULT } from '../models/automations';
import { info } from 'tauri-plugin-log-api';
import { v4 as uuidv4 } from 'uuid';
diff --git a/src/app/models/osc-message.ts b/src/app/models/osc-message.ts
index ad45619a..50f51c93 100644
--- a/src/app/models/osc-message.ts
+++ b/src/app/models/osc-message.ts
@@ -52,7 +52,7 @@ export function parseOSCMessage(message: OSCMessageRaw): OSCMessage {
export function parseOSCValue(value: OSCValueRaw): OSCValue {
let parsedValue: unknown;
- switch(value.kind) {
+ switch (value.kind) {
case 'int':
parsedValue = parseInt(value.value);
break;
diff --git a/src/app/models/telemetry-settings.ts b/src/app/models/telemetry-settings.ts
index 42d01529..dd5e4047 100644
--- a/src/app/models/telemetry-settings.ts
+++ b/src/app/models/telemetry-settings.ts
@@ -13,5 +13,5 @@ export const TELEMETRY_SETTINGS_DEFAULT: TelemetrySettings = {
version: 1,
enabled: true,
telemetryId: uuidv4(),
- lastHeartbeat: 0
+ lastHeartbeat: 0,
};
diff --git a/src/app/pipes/image-cache.pipe.ts b/src/app/pipes/image-cache.pipe.ts
index 871021a3..844471ac 100644
--- a/src/app/pipes/image-cache.pipe.ts
+++ b/src/app/pipes/image-cache.pipe.ts
@@ -1,6 +1,4 @@
-import { Input, Pipe, PipeTransform } from '@angular/core';
-import { TranslateService } from '@ngx-translate/core';
-import { TString } from '../models/translatable-string';
+import { Pipe, PipeTransform } from '@angular/core';
import { ImageCacheService } from '../services/image-cache.service';
@Pipe({
diff --git a/src/app/services/battery-automations/turn-off-devices-when-charging-automation.service.ts b/src/app/services/battery-automations/turn-off-devices-when-charging-automation.service.ts
index b82cc2c4..31922114 100644
--- a/src/app/services/battery-automations/turn-off-devices-when-charging-automation.service.ts
+++ b/src/app/services/battery-automations/turn-off-devices-when-charging-automation.service.ts
@@ -31,7 +31,11 @@ export class TurnOffDevicesWhenChargingAutomationService {
this.openvr.devices.subscribe((devices) => {
devices.forEach((device) => {
- if (device.isCharging && device.canPowerOff && !this.chargingDevices.includes(device.index)) {
+ if (
+ device.isCharging &&
+ device.canPowerOff &&
+ !this.chargingDevices.includes(device.index)
+ ) {
this.chargingDevices.push(device.index);
if (this.config.enabled && this.config.deviceClasses.includes(device.class)) {
info(
diff --git a/src/app/services/gpu-automations.service.ts b/src/app/services/gpu-automations.service.ts
index f9b7cc97..a905892f 100644
--- a/src/app/services/gpu-automations.service.ts
+++ b/src/app/services/gpu-automations.service.ts
@@ -195,7 +195,7 @@ export class GpuAutomationsService {
(getAutomationConfig().resetToDefault
? selectedDevice!.defaultPowerLimit!
: getAutomationConfig().powerLimit || selectedDevice!.defaultPowerLimit!) * 1000
- )
+ );
})
)
.subscribe();
diff --git a/src/app/services/image-cache.service.ts b/src/app/services/image-cache.service.ts
index f1db2a4c..75761f08 100644
--- a/src/app/services/image-cache.service.ts
+++ b/src/app/services/image-cache.service.ts
@@ -1,7 +1,6 @@
import { Injectable } from '@angular/core';
import { invoke } from '@tauri-apps/api';
-import { error, warn } from 'tauri-plugin-log-api';
-
+import { warn } from 'tauri-plugin-log-api';
@Injectable({
providedIn: 'root',
diff --git a/src/app/services/invite-automations.service.ts b/src/app/services/invite-automations.service.ts
index 13dbf2dc..2afbc330 100644
--- a/src/app/services/invite-automations.service.ts
+++ b/src/app/services/invite-automations.service.ts
@@ -4,7 +4,6 @@ import { AutomationConfigService } from './automation-config.service';
import { SleepService } from './sleep.service';
import { Notification, NotificationType, UserStatus } from 'vrchat';
import { info, warn } from 'tauri-plugin-log-api';
-import { notification } from '@tauri-apps/api';
import { firstValueFrom } from 'rxjs';
@Injectable({
diff --git a/src/app/services/openvr.service.ts b/src/app/services/openvr.service.ts
index be5e0991..7761c829 100644
--- a/src/app/services/openvr.service.ts
+++ b/src/app/services/openvr.service.ts
@@ -6,7 +6,6 @@ import { invoke } from '@tauri-apps/api/tauri';
import { OVRDevice, OVRDevicePose } from '../models/ovr-device';
import { BehaviorSubject, interval, Observable, startWith, Subject, takeUntil } from 'rxjs';
import { cloneDeep, orderBy } from 'lodash';
-import { message } from '@tauri-apps/api/dialog';
import { AppSettingsService } from './app-settings.service';
import { error, info } from 'tauri-plugin-log-api';
diff --git a/src/app/services/osc-automations/sleeping-animations-automation.service.ts b/src/app/services/osc-automations/sleeping-animations-automation.service.ts
index fed98f5a..a61ee62c 100644
--- a/src/app/services/osc-automations/sleeping-animations-automation.service.ts
+++ b/src/app/services/osc-automations/sleeping-animations-automation.service.ts
@@ -6,7 +6,15 @@ import {
SleepingAnimationsAutomationConfig,
} from '../../models/automations';
import { cloneDeep } from 'lodash';
-import { combineLatest, debounceTime, filter, firstValueFrom, map, pairwise, startWith } from 'rxjs';
+import {
+ combineLatest,
+ debounceTime,
+ filter,
+ firstValueFrom,
+ map,
+ pairwise,
+ startWith,
+} from 'rxjs';
import { SleepService } from '../sleep.service';
import { SleepingPose } from '../../models/sleeping-pose';
import { OscService } from '../osc.service';
@@ -48,7 +56,7 @@ export class SleepingAnimationsAutomationService {
startWith(false),
pairwise(),
filter(([oldIsEnabled, newIsEnabled]) => !oldIsEnabled && newIsEnabled),
- startWith(false),
+ startWith(false)
),
// Retrigger when sleep mode is enabled
this.sleep.mode.pipe(
@@ -72,37 +80,41 @@ export class SleepingAnimationsAutomationService {
}),
startWith([])
),
- ]).pipe(debounceTime(0)).subscribe(async ([pose]) => {
- if (!this.config.enabled) return;
- if (this.config.onlyIfSleepModeEnabled && !(await firstValueFrom(this.sleep.mode))) return;
- if (this.config.onlyIfAllTrackersTurnedOff) {
- const devices = await firstValueFrom(this.openvr.devices);
- const trackersFound = !!devices.find((d) => d.class === 'GenericTracker' && d.canPowerOff);
- if (trackersFound) return;
- }
- // Combine OSC scripts
- const script: OscScript = { version: 1, commands: [] };
- const enableFootUnlock = !!(
- this.config.releaseFootLockOnPoseChange &&
- this.config.oscScripts.FOOT_UNLOCK &&
- this.config.oscScripts.FOOT_UNLOCK
- );
- if (enableFootUnlock) script.commands.push(...this.config.oscScripts.FOOT_UNLOCK!.commands);
- let scriptTime = 0;
- if (this.config.oscScripts[pose]) {
- scriptTime = getOscScriptDuration(this.config.oscScripts[pose]!);
- script.commands.push(...this.config.oscScripts[pose]!.commands);
- }
- if (enableFootUnlock) {
- let minimumDelayRemainder = this.config.footLockReleaseWindow - scriptTime;
- if (minimumDelayRemainder > 0) {
- script.commands.push({ type: 'SLEEP', duration: minimumDelayRemainder });
+ ])
+ .pipe(debounceTime(0))
+ .subscribe(async ([pose]) => {
+ if (!this.config.enabled) return;
+ if (this.config.onlyIfSleepModeEnabled && !(await firstValueFrom(this.sleep.mode))) return;
+ if (this.config.onlyIfAllTrackersTurnedOff) {
+ const devices = await firstValueFrom(this.openvr.devices);
+ const trackersFound = !!devices.find(
+ (d) => d.class === 'GenericTracker' && d.canPowerOff
+ );
+ if (trackersFound) return;
}
- script.commands.push(...this.config.oscScripts.FOOT_LOCK!.commands);
- }
- // Queue script
- this.osc.queueScript(script, 'SLEEPING_ANIMATION_AUTOMATION_POSE_CHANGE');
- });
+ // Combine OSC scripts
+ const script: OscScript = { version: 1, commands: [] };
+ const enableFootUnlock = !!(
+ this.config.releaseFootLockOnPoseChange &&
+ this.config.oscScripts.FOOT_UNLOCK &&
+ this.config.oscScripts.FOOT_UNLOCK
+ );
+ if (enableFootUnlock) script.commands.push(...this.config.oscScripts.FOOT_UNLOCK!.commands);
+ let scriptTime = 0;
+ if (this.config.oscScripts[pose]) {
+ scriptTime = getOscScriptDuration(this.config.oscScripts[pose]!);
+ script.commands.push(...this.config.oscScripts[pose]!.commands);
+ }
+ if (enableFootUnlock) {
+ let minimumDelayRemainder = this.config.footLockReleaseWindow - scriptTime;
+ if (minimumDelayRemainder > 0) {
+ script.commands.push({ type: 'SLEEP', duration: minimumDelayRemainder });
+ }
+ script.commands.push(...this.config.oscScripts.FOOT_LOCK!.commands);
+ }
+ // Queue script
+ this.osc.queueScript(script, 'SLEEPING_ANIMATION_AUTOMATION_POSE_CHANGE');
+ });
}
private subscribeToSleepMode() {
diff --git a/src/app/services/update.service.ts b/src/app/services/update.service.ts
index 179c142e..fb3eb78c 100644
--- a/src/app/services/update.service.ts
+++ b/src/app/services/update.service.ts
@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
-import { BehaviorSubject, Observable } from 'rxjs';
+import { BehaviorSubject, filter, interval, Observable, switchMap, take } from 'rxjs';
import { checkUpdate, installUpdate, UpdateManifest } from '@tauri-apps/api/updater';
import { relaunch } from '@tauri-apps/api/process';
import { listen } from '@tauri-apps/api/event';
@@ -40,7 +40,17 @@ export class UpdateService {
.subscribe();
}
});
+ // Check for updates on start
await this.checkForUpdate(true);
+ // Check for updates every 7 days in case Oyasumi is left running for a long time.
+ interval(1000 * 3600 * 24 * 7).subscribe(() => this.checkForUpdate());
+ // Check for updates every 10 minutes until at least one update check has been done successfully.
+ interval(1000 * 60 * 10)
+ .pipe(
+ switchMap(() => this._updateAvailable.pipe(take(1))),
+ filter((info) => !info.checked)
+ )
+ .subscribe(() => this.checkForUpdate());
}
async checkForUpdate(showDialog = false) {
diff --git a/src/app/services/vrchat.service.ts b/src/app/services/vrchat.service.ts
index a3614e9d..1a8d4cdb 100644
--- a/src/app/services/vrchat.service.ts
+++ b/src/app/services/vrchat.service.ts
@@ -1,13 +1,6 @@
import { Injectable } from '@angular/core';
import { Body, Client, getClient, Response, ResponseType } from '@tauri-apps/api/http';
-import {
- APIConfig,
- CurrentUser,
- Notification,
- NotificationType,
- UserStatus,
- LimitedUser,
-} from 'vrchat/dist';
+import { APIConfig, CurrentUser, LimitedUser, Notification, UserStatus } from 'vrchat/dist';
import { parse as parseSetCookieHeader } from 'set-cookie-parser';
import { Store } from 'tauri-plugin-store-api';
import { SETTINGS_FILE } from '../globals';
@@ -157,7 +150,7 @@ export class VRChatService {
public async login(username: string, password: string): Promise
{
if (this._status.value !== 'LOGGED_OUT')
throw new Error('Tried calling login() while already logged in');
- this._user.next(await this.getCurrentUser({ username, password }));
+ this._user.next(await this.getCurrentUser({ username, password }, true));
// If we got here, we have a user, so we are logged in (and have cookies)
this._status.next('LOGGED_IN');
info(`[VRChat] Logged in: ${this._user.value?.displayName}`);
@@ -355,6 +348,7 @@ export class VRChatService {
});
},
});
+ console.log('RESPONSE', response);
if (response.result && response.result.ok) {
// Add friends to list
friends.push(...response.result.data);
@@ -529,6 +523,7 @@ export class VRChatService {
responseType: ResponseType.JSON,
}
);
+ console.log('RESPONSE /auth/user', response);
// If we received a 401, there is probably an error included
if (response.status === 401) {
// Try parse the error message
@@ -591,29 +586,33 @@ export class VRChatService {
}
private async parseResponseCookies(response: Response) {
- if (!response.headers['set-cookie']) return;
- const cookies = parseSetCookieHeader(response.headers['set-cookie']);
- for (let cookie of cookies) {
- const expiry = Math.floor((cookie.expires || new Date()).getTime() / 1000);
- switch (cookie.name) {
- case 'apiKey':
- await this.updateSettings({
- apiKey: cookie.value,
- apiKeyExpiry: Math.floor(Date.now() / 1000) + 3600, // Always shift this one hour into the future
- });
- break;
- case 'auth':
- await this.updateSettings({
- authCookie: cookie.value,
- authCookieExpiry: expiry,
- });
- break;
- case 'twoFactorAuth':
- await this.updateSettings({
- twoFactorCookie: cookie.value,
- twoFactorCookieExpiry: expiry,
- });
- break;
+ if (!response.rawHeaders['set-cookie']) return;
+ const cookieHeaders = response.rawHeaders['set-cookie'];
+ for (let cookieHeader of cookieHeaders) {
+ const cookies = parseSetCookieHeader(cookieHeader);
+ for (let cookie of cookies) {
+ console.log('COOKIE', cookie);
+ const expiry = Math.floor((cookie.expires || new Date()).getTime() / 1000);
+ switch (cookie.name) {
+ case 'apiKey':
+ await this.updateSettings({
+ apiKey: cookie.value,
+ apiKeyExpiry: Math.floor(Date.now() / 1000) + 3600, // Always shift this one hour into the future
+ });
+ break;
+ case 'auth':
+ await this.updateSettings({
+ authCookie: cookie.value,
+ authCookieExpiry: expiry,
+ });
+ break;
+ case 'twoFactorAuth':
+ await this.updateSettings({
+ twoFactorCookie: cookie.value,
+ twoFactorCookieExpiry: expiry,
+ });
+ break;
+ }
}
}
}
diff --git a/src/app/utils/cached-value.ts b/src/app/utils/cached-value.ts
index b8dca03a..113ed8cb 100644
--- a/src/app/utils/cached-value.ts
+++ b/src/app/utils/cached-value.ts
@@ -1,6 +1,7 @@
import { CACHE_FILE } from '../globals';
import { Store } from 'tauri-plugin-store-api';
import { BehaviorSubject, filter, firstValueFrom } from 'rxjs';
+
interface CachedValueEntry {
value: T;
lastSet: number;
diff --git a/src/app/views/dashboard-view/views/about-view/about-view.component.html b/src/app/views/dashboard-view/views/about-view/about-view.component.html
index f01dd547..393c8b05 100644
--- a/src/app/views/dashboard-view/views/about-view/about-view.component.html
+++ b/src/app/views/dashboard-view/views/about-view/about-view.component.html
@@ -39,11 +39,11 @@
about.translations
diff --git a/src/app/views/dashboard-view/views/auto-invite-request-accept-view/auto-invite-request-accept-view.component.spec.ts b/src/app/views/dashboard-view/views/auto-invite-request-accept-view/auto-invite-request-accept-view.component.spec.ts
index f046cedc..ec237489 100644
--- a/src/app/views/dashboard-view/views/auto-invite-request-accept-view/auto-invite-request-accept-view.component.spec.ts
+++ b/src/app/views/dashboard-view/views/auto-invite-request-accept-view/auto-invite-request-accept-view.component.spec.ts
@@ -8,9 +8,8 @@ describe('AutoInviteRequestAcceptViewComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
- declarations: [ AutoInviteRequestAcceptViewComponent ]
- })
- .compileComponents();
+ declarations: [AutoInviteRequestAcceptViewComponent],
+ }).compileComponents();
fixture = TestBed.createComponent(AutoInviteRequestAcceptViewComponent);
component = fixture.componentInstance;
diff --git a/src/app/views/dashboard-view/views/auto-invite-request-accept-view/auto-invite-request-accept-view.component.ts b/src/app/views/dashboard-view/views/auto-invite-request-accept-view/auto-invite-request-accept-view.component.ts
index a5340ca9..3c874465 100644
--- a/src/app/views/dashboard-view/views/auto-invite-request-accept-view/auto-invite-request-accept-view.component.ts
+++ b/src/app/views/dashboard-view/views/auto-invite-request-accept-view/auto-invite-request-accept-view.component.ts
@@ -13,7 +13,6 @@ import { LimitedUser } from 'vrchat/dist';
import {
AutoAcceptInviteRequestsAutomationConfig,
AUTOMATION_CONFIGS_DEFAULT,
- ChangeStatusBasedOnPlayerCountAutomationConfig,
} from '../../../../models/automations';
import { AutomationConfigService } from '../../../../services/automation-config.service';
diff --git a/src/app/views/dashboard-view/views/gpu-automations-view/power-limit-input/power-limit-input.component.scss b/src/app/views/dashboard-view/views/gpu-automations-view/power-limit-input/power-limit-input.component.scss
index f4fd8e5a..7b44cacd 100644
--- a/src/app/views/dashboard-view/views/gpu-automations-view/power-limit-input/power-limit-input.component.scss
+++ b/src/app/views/dashboard-view/views/gpu-automations-view/power-limit-input/power-limit-input.component.scss
@@ -37,5 +37,3 @@
pointer-events: none;
}
}
-
-
diff --git a/src/app/views/dashboard-view/views/settings-view/settings-debug-tab/settings-debug-tab.component.ts b/src/app/views/dashboard-view/views/settings-view/settings-debug-tab/settings-debug-tab.component.ts
index a2f7f019..d9b6baa7 100644
--- a/src/app/views/dashboard-view/views/settings-view/settings-debug-tab/settings-debug-tab.component.ts
+++ b/src/app/views/dashboard-view/views/settings-view/settings-debug-tab/settings-debug-tab.component.ts
@@ -11,7 +11,7 @@ import { Store } from 'tauri-plugin-store-api';
import { SETTINGS_KEY_AUTOMATION_CONFIGS } from '../../../../../services/automation-config.service';
import { Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
-import { error, info } from 'tauri-plugin-log-api';
+import { error } from 'tauri-plugin-log-api';
@Component({
selector: 'app-settings-debug-tab',
diff --git a/src/app/views/dashboard-view/views/settings-view/settings-updates-tab/settings-updates-tab.component.ts b/src/app/views/dashboard-view/views/settings-view/settings-updates-tab/settings-updates-tab.component.ts
index 93e48395..c34b69bd 100644
--- a/src/app/views/dashboard-view/views/settings-view/settings-updates-tab/settings-updates-tab.component.ts
+++ b/src/app/views/dashboard-view/views/settings-view/settings-updates-tab/settings-updates-tab.component.ts
@@ -25,7 +25,7 @@ export class SettingsUpdatesTabComponent extends SettingsTabComponent {
settingsService: AppSettingsService,
private update: UpdateService,
private http: HttpClient,
- private sanitizer: DomSanitizer,
+ private sanitizer: DomSanitizer
) {
super(settingsService);
}
diff --git a/src/app/views/dashboard-view/views/settings-view/settings-vrchat-tab/settings-vrchat-tab.component.ts b/src/app/views/dashboard-view/views/settings-view/settings-vrchat-tab/settings-vrchat-tab.component.ts
index 6c45e4f1..8a204562 100644
--- a/src/app/views/dashboard-view/views/settings-view/settings-vrchat-tab/settings-vrchat-tab.component.ts
+++ b/src/app/views/dashboard-view/views/settings-view/settings-vrchat-tab/settings-vrchat-tab.component.ts
@@ -36,7 +36,7 @@ export class SettingsVRChatTabComponent extends SettingsTabComponent {
}
login() {
- this.vrchat.showLoginModal();
+ this.vrchat.showLoginModal();
}
async logout() {
diff --git a/src/app/views/dashboard-view/views/status-automations-view/status-automations-view.component.scss b/src/app/views/dashboard-view/views/status-automations-view/status-automations-view.component.scss
index c75b4da8..c0d16248 100644
--- a/src/app/views/dashboard-view/views/status-automations-view/status-automations-view.component.scss
+++ b/src/app/views/dashboard-view/views/status-automations-view/status-automations-view.component.scss
@@ -1,4 +1,4 @@
-@use "sass:math";
+@use 'sass:math';
@import 'shadows';
diff --git a/src/assets/i18n/ko.json b/src/assets/i18n/ko.json
index 119c226d..52eb48b7 100644
--- a/src/assets/i18n/ko.json
+++ b/src/assets/i18n/ko.json
@@ -462,4 +462,4 @@
"noFriends": "친구 목록이 비어있어요"
}
}
-}
\ No newline at end of file
+}