Refactor Discord RPC

This commit is contained in:
Natsumi
2025-08-01 17:06:13 +12:00
parent 7946ff63ae
commit bc2211f332
7 changed files with 332 additions and 274 deletions

View File

@@ -16,12 +16,13 @@ namespace VRCX
{
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
public static readonly Discord Instance;
private readonly ReaderWriterLockSlim m_Lock;
private readonly RichPresence m_Presence;
private DiscordRpcClient m_Client;
private readonly Timer m_Timer;
private bool m_Active;
public static string DiscordAppId;
private readonly ReaderWriterLockSlim _lock;
private readonly RichPresence _presence;
private DiscordRpcClient _client;
private readonly Timer _timer;
private bool _active;
private string _discordAppId;
private const string VrcxUrl = "https://vrcx.app";
static Discord()
{
@@ -30,22 +31,22 @@ namespace VRCX
public Discord()
{
m_Lock = new ReaderWriterLockSlim();
m_Presence = new RichPresence();
m_Timer = new Timer(TimerCallback, null, -1, -1);
_lock = new ReaderWriterLockSlim();
_presence = new RichPresence();
_timer = new Timer(TimerCallback, null, -1, -1);
}
public void Init()
{
m_Timer.Change(0, 1000);
_timer.Change(0, 3000);
}
public void Exit()
{
lock (this)
{
m_Timer.Change(-1, -1);
m_Client?.Dispose();
_timer.Change(-1, -1);
_client?.Dispose();
}
}
@@ -66,41 +67,41 @@ namespace VRCX
private void Update()
{
if (m_Client == null && m_Active)
if (_client == null && _active)
{
m_Client = new DiscordRpcClient(DiscordAppId);
if (!m_Client.Initialize())
_client = new DiscordRpcClient(_discordAppId);
if (!_client.Initialize())
{
m_Client.Dispose();
m_Client = null;
_client.Dispose();
_client = null;
}
}
if (m_Client != null && !m_Active)
if (_client != null && !_active)
{
m_Client.Dispose();
m_Client = null;
_client.Dispose();
_client = null;
}
if (m_Client != null && !m_Lock.IsWriteLockHeld)
if (_client != null && !_lock.IsWriteLockHeld)
{
m_Lock.EnterReadLock();
_lock.EnterReadLock();
try
{
m_Client.SetPresence(m_Presence);
_client.SetPresence(_presence);
}
finally
{
m_Lock.ExitReadLock();
_lock.ExitReadLock();
}
m_Client.Invoke();
_client.Invoke();
}
}
public bool SetActive(bool active)
{
m_Active = active;
return m_Active;
_active = active;
return _active;
}
// https://stackoverflow.com/questions/1225052/best-way-to-shorten-utf8-string-based-on-byte-length
@@ -118,107 +119,113 @@ namespace VRCX
}
return Encoding.UTF8.GetString(bytesArr, 0, bytesArr.Length - bytesToRemove);
}
public void SetText(string details, string state)
public void SetAssets(
string details,
string state,
string stateUrl,
string largeKey,
string largeText,
string smallKey,
string smallText,
double startUnixMilliseconds,
double endUnixMilliseconds,
string partyId,
int partySize,
int partyMax,
string buttonText,
string buttonUrl,
string appId,
int activityType)
{
if (m_Client == null || m_Lock.IsReadLockHeld)
return;
m_Lock.EnterWriteLock();
try
{
m_Presence.Details = LimitByteLength(details, 127);
m_Presence.State = LimitByteLength(state, 127);
}
finally
{
m_Lock.ExitWriteLock();
}
}
public void SetAssets(string largeKey, string largeText, string smallKey, string smallText, string partyId, int partySize, int partyMax, string buttonText, string buttonUrl, string appId, int activityType = 0)
{
m_Lock.EnterWriteLock();
_lock.EnterWriteLock();
try
{
if (string.IsNullOrEmpty(largeKey) &&
string.IsNullOrEmpty(smallKey))
{
m_Presence.Assets = null;
_presence.Assets = null;
_presence.Party = null;
_presence.Timestamps = null;
_lock.ExitWriteLock();
return;
}
_presence.Details = LimitByteLength(details, 127);
// _presence.DetailsUrl
_presence.StateUrl = !string.IsNullOrEmpty(stateUrl) ? stateUrl : null;
_presence.State = LimitByteLength(state, 127);
_presence.Assets ??= new Assets();
_presence.Assets.LargeImageKey = largeKey;
_presence.Assets.LargeImageText = largeText;
_presence.Assets.LargeImageUrl = VrcxUrl;
_presence.Assets.SmallImageKey = smallKey;
_presence.Assets.SmallImageText = smallText;
// m_Presence.Assets.SmallImageUrl
if (startUnixMilliseconds == 0)
{
_presence.Timestamps = null;
}
else
{
m_Presence.Assets ??= new Assets();
m_Presence.Party ??= new Party();
m_Presence.Assets.LargeImageKey = largeKey;
m_Presence.Assets.LargeImageText = largeText;
m_Presence.Assets.SmallImageKey = smallKey;
m_Presence.Assets.SmallImageText = smallText;
m_Presence.Party.ID = partyId;
m_Presence.Party.Size = partySize;
m_Presence.Party.Max = partyMax;
m_Presence.Type = (ActivityType)activityType;
Button[] buttons = [];
if (!string.IsNullOrEmpty(buttonUrl))
{
buttons =
[
new Button { Label = buttonText, Url = buttonUrl }
];
}
m_Presence.Buttons = buttons;
if (DiscordAppId != appId)
{
DiscordAppId = appId;
if (m_Client != null)
{
m_Client.Dispose();
m_Client = null;
}
Update();
}
}
}
finally
{
m_Lock.ExitWriteLock();
}
}
public void SetTimestamps(double startUnixMilliseconds, double endUnixMilliseconds)
{
var _startUnixMilliseconds = (ulong)startUnixMilliseconds;
var _endUnixMilliseconds = (ulong)endUnixMilliseconds;
m_Lock.EnterWriteLock();
try
{
if (_startUnixMilliseconds == 0)
{
m_Presence.Timestamps = null;
}
else
{
m_Presence.Timestamps ??= new Timestamps();
m_Presence.Timestamps.StartUnixMilliseconds = _startUnixMilliseconds;
if (_endUnixMilliseconds == 0)
{
m_Presence.Timestamps.End = null;
}
_presence.Timestamps ??= new Timestamps();
_presence.Timestamps.StartUnixMilliseconds = (ulong)startUnixMilliseconds;
if (endUnixMilliseconds == 0)
_presence.Timestamps.End = null;
else
_presence.Timestamps.EndUnixMilliseconds = (ulong)endUnixMilliseconds;
}
if (partyMax == 0)
{
_presence.Party = null;
}
else
{
_presence.Party ??= new Party();
_presence.Party.ID = partyId;
_presence.Party.Size = partySize;
_presence.Party.Max = partyMax;
}
_presence.Type = (ActivityType)activityType;
_presence.StatusDisplay = StatusDisplayType.Details;
Button[] buttons = [];
if (!string.IsNullOrEmpty(buttonUrl))
{
buttons =
[
new Button { Label = buttonText, Url = buttonUrl }
];
}
_presence.Buttons = buttons;
if (_discordAppId != appId)
{
_discordAppId = appId;
if (_client != null)
{
m_Presence.Timestamps.EndUnixMilliseconds = _endUnixMilliseconds;
_client.Dispose();
_client = null;
}
Update();
}
}
catch (Exception ex)
{
_logger.Error(ex, "Error setting timestamps in Discord Rich Presence {Error}", ex.Message);
_logger.Error(ex, "Error setting Discord Rich Presence assets: {Error}", ex.Message);
}
finally
{
m_Lock.ExitWriteLock();
_lock.ExitWriteLock();
}
}
}

View File

@@ -93,14 +93,14 @@
<ItemGroup>
<PackageReference Include="CefSharp.OffScreen.NETCore" Version="138.0.170" />
<PackageReference Include="CefSharp.WinForms.NETCore" Version="138.0.170" />
<PackageReference Include="DiscordRichPresence" Version="1.3.0.28" />
<PackageReference Include="DiscordRichPresence" Version="1.5.0.51" />
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="6.0.2" />
<PackageReference Include="SharpDX.Direct3D11" Version="4.2.0" />
<PackageReference Include="SharpDX.Mathematics" Version="4.2.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.6" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.7" />
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
<PackageReference Include="System.Data.SQLite" Version="1.0.119" />
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.119" />

View File

@@ -28,22 +28,12 @@ export const useLocationStore = defineStore('Location', () => {
const state = reactive({
lastLocation: {
date: 0,
date: null,
location: '',
name: '',
playerList: new Map(),
friendList: new Map()
},
lastLocation$: {
tag: '',
instanceId: '',
accessType: '',
worldName: '',
worldCapacity: 0,
joinUrl: '',
statusName: '',
statusImage: ''
},
lastLocationDestination: '',
lastLocationDestinationTime: 0
});
@@ -55,13 +45,6 @@ export const useLocationStore = defineStore('Location', () => {
}
});
const lastLocation$ = computed({
get: () => state.lastLocation$,
set: (value) => {
state.lastLocation$ = value;
}
});
const lastLocationDestination = computed({
get: () => state.lastLocationDestination,
set: (value) => {
@@ -153,7 +136,7 @@ export const useLocationStore = defineStore('Location', () => {
const L = parseLocation(location);
state.lastLocation.location = location;
state.lastLocation.date = dt;
state.lastLocation.date = Date.now();
const entry = {
created_at: dt,
@@ -174,7 +157,7 @@ export const useLocationStore = defineStore('Location', () => {
instanceStore.applyGroupDialogInstances();
} else {
state.lastLocation.location = '';
state.lastLocation.date = '';
state.lastLocation.date = null;
}
}
@@ -218,7 +201,7 @@ export const useLocationStore = defineStore('Location', () => {
gameLogStore.addGameLog(entry);
}
database.addGamelogJoinLeaveBulk(dataBaseEntries);
if (state.lastLocation.date !== 0) {
if (state.lastLocation.date !== null && state.lastLocation.date > 0) {
const update = {
time: dateTimeStamp - state.lastLocation.date,
created_at: new Date(state.lastLocation.date).toJSON()
@@ -248,7 +231,6 @@ export const useLocationStore = defineStore('Location', () => {
return {
state,
lastLocation,
lastLocation$,
lastLocationDestination,
lastLocationDestinationTime,
updateCurrentUserLocation,

View File

@@ -1,6 +1,6 @@
import { defineStore } from 'pinia';
import { computed, reactive } from 'vue';
import { userRequest, worldRequest } from '../../api';
import { worldRequest } from '../../api';
import configRepository from '../../service/config';
import {
getGroupName,
@@ -14,7 +14,6 @@ import { useGameLogStore } from '../gameLog';
import { useLocationStore } from '../location';
import { useUpdateLoopStore } from '../updateLoop';
import { useUserStore } from '../user';
import { useWorldStore } from '../world';
import { useAdvancedSettingsStore } from './advanced';
import { ActivityType } from '../../shared/constants/discord';
@@ -24,7 +23,6 @@ export const useDiscordPresenceSettingsStore = defineStore(
const locationStore = useLocationStore();
const gameStore = useGameStore();
const advancedSettingsStore = useAdvancedSettingsStore();
const worldStore = useWorldStore();
const gameLogStore = useGameLogStore();
const userStore = useUserStore();
const updateLoopStore = useUpdateLoopStore();
@@ -35,7 +33,20 @@ export const useDiscordPresenceSettingsStore = defineStore(
discordHideInvite: true,
discordJoinButton: false,
discordHideImage: false,
isDiscordActive: false
isDiscordActive: false,
lastLocationDetails: {
tag: '',
instanceName: '',
accessType: '',
worldId: '',
worldName: '',
thumbnailImageUrl: '',
worldCapacity: 0,
joinUrl: '',
worldLink: '',
accessName: '',
groupAccessType: ''
}
});
async function initDiscordPresenceSettings() {
@@ -98,186 +109,218 @@ export const useDiscordPresenceSettingsStore = defineStore(
initDiscordPresenceSettings();
function updateDiscord() {
let platform;
async function updateDiscord() {
let currentLocation = locationStore.lastLocation.location;
let timeStamp = locationStore.lastLocation.date;
let startTime = locationStore.lastLocation.date;
if (locationStore.lastLocation.location === 'traveling') {
currentLocation = locationStore.lastLocationDestination;
timeStamp = locationStore.lastLocationDestinationTime;
startTime = locationStore.lastLocationDestinationTime;
}
if (advancedSettingsStore.gameLogDisabled) {
// game log disabled, use API location
currentLocation = userStore.currentUser.$locationTag;
startTime = userStore.currentUser.$location_at;
if (userStore.currentUser.$travelingToLocation) {
currentLocation =
userStore.currentUser.$travelingToLocation;
}
}
if (
!state.discordActive ||
(!gameStore.isGameRunning &&
!advancedSettingsStore.gameLogDisabled) ||
(!currentLocation && !locationStore.lastLocation$.tag)
!isRealInstance(currentLocation)
) {
setIsDiscordActive(false);
return;
}
setIsDiscordActive(true);
let L = locationStore.lastLocation$;
if (currentLocation !== locationStore.lastLocation$.tag) {
Discord.SetTimestamps(timeStamp, 0);
L = parseLocation(currentLocation);
L.worldName = '';
L.thumbnailImageUrl = '';
L.worldCapacity = 0;
L.joinUrl = '';
L.accessName = '';
if (L.worldId) {
const ref = worldStore.cachedWorlds.get(L.worldId);
if (ref) {
L.worldName = ref.name;
L.thumbnailImageUrl = ref.thumbnailImageUrl;
L.worldCapacity = ref.capacity;
} else {
worldRequest
.getWorld({
worldId: L.worldId
})
.then((args) => {
L.worldName = args.ref.name;
L.thumbnailImageUrl =
args.ref.thumbnailImageUrl;
L.worldCapacity = args.ref.capacity;
return args;
});
if (currentLocation !== state.lastLocationDetails.tag) {
const L = parseLocation(currentLocation);
state.lastLocationDetails = {
tag: L.tag,
instanceName: L.instanceName,
accessType: L.accessType,
worldId: L.worldId,
worldName: '',
thumbnailImageUrl: '',
worldCapacity: 0,
joinUrl: '',
worldLink: '',
accessName: '',
groupAccessType: ''
};
try {
const args = await worldRequest.getCachedWorld({
worldId: L.worldId
});
state.lastLocationDetails.worldName = args.ref.name;
state.lastLocationDetails.thumbnailImageUrl =
args.ref.thumbnailImageUrl;
state.lastLocationDetails.worldCapacity = args.ref.capacity;
if (args.ref.releaseStatus === 'public') {
state.lastLocationDetails.worldLink = `https://vrchat.com/home/world/${L.worldId}`;
}
if (gameStore.isGameNoVR) {
platform = 'Desktop';
} else {
platform = 'VR';
}
let groupAccessType = '';
if (L.groupAccessType) {
if (L.groupAccessType === 'public') {
groupAccessType = 'Public';
} else if (L.groupAccessType === 'plus') {
groupAccessType = 'Plus';
}
}
switch (L.accessType) {
case 'public':
L.joinUrl = getLaunchURL(L);
L.accessName = `Public #${L.instanceName} (${platform})`;
break;
case 'invite+':
L.accessName = `Invite+ #${L.instanceName} (${platform})`;
break;
case 'invite':
L.accessName = `Invite #${L.instanceName} (${platform})`;
break;
case 'friends':
L.accessName = `Friends #${L.instanceName} (${platform})`;
break;
case 'friends+':
L.accessName = `Friends+ #${L.instanceName} (${platform})`;
break;
case 'group':
L.accessName = `Group #${L.instanceName} (${platform})`;
getGroupName(L.groupId).then((groupName) => {
if (groupName) {
L.accessName = `Group${groupAccessType}(${groupName}) #${L.instanceName} (${platform})`;
}
});
break;
} catch (e) {
console.error(
`Failed to get world details for ${L.worldId}`,
e
);
}
let platform = gameStore.isGameNoVR ? 'Desktop' : 'VR';
if (L.groupAccessType) {
if (L.groupAccessType === 'public') {
state.lastLocationDetails.groupAccessType = 'Public';
} else if (L.groupAccessType === 'plus') {
state.lastLocationDetails.groupAccessType = 'Plus';
}
}
locationStore.lastLocation$ = L;
switch (L.accessType) {
case 'public':
state.lastLocationDetails.joinUrl = getLaunchURL(L);
state.lastLocationDetails.accessName = `Public #${L.instanceName} (${platform})`;
break;
case 'invite+':
state.lastLocationDetails.accessName = `Invite+ #${L.instanceName} (${platform})`;
break;
case 'invite':
state.lastLocationDetails.accessName = `Invite #${L.instanceName} (${platform})`;
break;
case 'friends':
state.lastLocationDetails.accessName = `Friends #${L.instanceName} (${platform})`;
break;
case 'friends+':
state.lastLocationDetails.accessName = `Friends+ #${L.instanceName} (${platform})`;
break;
case 'group':
state.lastLocationDetails.accessName = `Group #${L.instanceName} (${platform})`;
try {
const groupName = await getGroupName(L.groupId);
state.lastLocationDetails.accessName = `Group${state.lastLocationDetails.groupAccessType}(${groupName}) #${L.instanceName} (${platform})`;
} catch (e) {
console.error(
`Failed to get group name for ${L.groupId}`,
e
);
}
break;
}
}
setIsDiscordActive(true);
let hidePrivate = false;
if (
state.discordHideInvite &&
(L.accessType === 'invite' ||
L.accessType === 'invite+' ||
L.groupAccessType === 'members')
(state.lastLocationDetails.accessType === 'invite' ||
state.lastLocationDetails.accessType === 'invite+' ||
state.lastLocationDetails.groupAccessType === 'members')
) {
hidePrivate = true;
}
let statusName = '';
let statusImage = '';
switch (userStore.currentUser.status) {
case 'active':
L.statusName = 'Online';
L.statusImage = 'active';
statusName = 'Online';
statusImage = 'active';
break;
case 'join me':
L.statusName = 'Join Me';
L.statusImage = 'joinme';
statusName = 'Join Me';
statusImage = 'joinme';
break;
case 'ask me':
L.statusName = 'Ask Me';
L.statusImage = 'askme';
statusName = 'Ask Me';
statusImage = 'askme';
if (state.discordHideInvite) {
hidePrivate = true;
}
break;
case 'busy':
L.statusName = 'Do Not Disturb';
L.statusImage = 'busy';
statusName = 'Do Not Disturb';
statusImage = 'busy';
hidePrivate = true;
break;
default:
statusName = 'Offline';
statusImage = 'offline';
hidePrivate = true;
break;
}
let details = state.lastLocationDetails.worldName;
let stateText = state.lastLocationDetails.accessName;
let endTime = 0;
let activityType = ActivityType.Playing;
let appId = '883308884863901717';
let bigIcon = 'vrchat';
let partyId = `${L.worldId}:${L.instanceName}`;
let stateUrl = state.lastLocationDetails.worldLink;
let partyId = `${state.lastLocationDetails.worldId}:${state.lastLocationDetails.instanceName}`;
let partySize = locationStore.lastLocation.playerList.size;
let partyMaxSize = L.worldCapacity;
let partyMaxSize = state.lastLocationDetails.worldCapacity;
if (partySize > partyMaxSize) {
partyMaxSize = partySize;
}
let buttonText = 'Join';
let buttonUrl = L.joinUrl;
if (!state.discordJoinButton) {
buttonText = '';
buttonUrl = '';
}
if (!state.discordInstance) {
partySize = 0;
partyMaxSize = 0;
stateText = '';
}
if (hidePrivate) {
partyId = '';
partySize = 0;
partyMaxSize = 0;
let buttonText = 'Join';
let buttonUrl = state.lastLocationDetails.joinUrl;
if (!state.discordJoinButton) {
buttonText = '';
buttonUrl = '';
} else if (isRpcWorld(L.tag)) {
}
if (isRpcWorld(state.lastLocationDetails.tag)) {
// custom world rpc
if (
L.worldId === 'wrld_f20326da-f1ac-45fc-a062-609723b097b1' ||
L.worldId === 'wrld_10e5e467-fc65-42ed-8957-f02cace1398c' ||
L.worldId === 'wrld_04899f23-e182-4a8d-b2c7-2c74c7c15534'
state.lastLocationDetails.worldId ===
'wrld_f20326da-f1ac-45fc-a062-609723b097b1' ||
state.lastLocationDetails.worldId ===
'wrld_10e5e467-fc65-42ed-8957-f02cace1398c' ||
state.lastLocationDetails.worldId ===
'wrld_04899f23-e182-4a8d-b2c7-2c74c7c15534'
) {
activityType = ActivityType.Listening;
appId = '784094509008551956';
bigIcon = 'pypy';
} else if (
L.worldId === 'wrld_42377cf1-c54f-45ed-8996-5875b0573a83' ||
L.worldId === 'wrld_dd6d2888-dbdc-47c2-bc98-3d631b2acd7c'
state.lastLocationDetails.worldId ===
'wrld_42377cf1-c54f-45ed-8996-5875b0573a83' ||
state.lastLocationDetails.worldId ===
'wrld_dd6d2888-dbdc-47c2-bc98-3d631b2acd7c'
) {
activityType = ActivityType.Listening;
appId = '846232616054030376';
bigIcon = 'vr_dancing';
} else if (
L.worldId === 'wrld_52bdcdab-11cd-4325-9655-0fb120846945' ||
L.worldId === 'wrld_2d40da63-8f1f-4011-8a9e-414eb8530acd'
state.lastLocationDetails.worldId ===
'wrld_52bdcdab-11cd-4325-9655-0fb120846945' ||
state.lastLocationDetails.worldId ===
'wrld_2d40da63-8f1f-4011-8a9e-414eb8530acd'
) {
activityType = ActivityType.Listening;
appId = '939473404808007731';
bigIcon = 'zuwa_zuwa_dance';
} else if (
L.worldId === 'wrld_74970324-58e8-4239-a17b-2c59dfdf00db' ||
L.worldId === 'wrld_db9d878f-6e76-4776-8bf2-15bcdd7fc445' ||
L.worldId === 'wrld_435bbf25-f34f-4b8b-82c6-cd809057eb8e' ||
L.worldId === 'wrld_f767d1c8-b249-4ecc-a56f-614e433682c8'
state.lastLocationDetails.worldId ===
'wrld_74970324-58e8-4239-a17b-2c59dfdf00db' ||
state.lastLocationDetails.worldId ===
'wrld_db9d878f-6e76-4776-8bf2-15bcdd7fc445' ||
state.lastLocationDetails.worldId ===
'wrld_435bbf25-f34f-4b8b-82c6-cd809057eb8e' ||
state.lastLocationDetails.worldId ===
'wrld_f767d1c8-b249-4ecc-a56f-614e433682c8'
) {
activityType = ActivityType.Watching;
appId = '968292722391785512';
bigIcon = 'ls_media';
} else if (
L.worldId === 'wrld_266523e8-9161-40da-acd0-6bd82e075833' ||
L.worldId === 'wrld_27c7e6b2-d938-447e-a270-3d1a873e2cf3'
state.lastLocationDetails.worldId ===
'wrld_266523e8-9161-40da-acd0-6bd82e075833' ||
state.lastLocationDetails.worldId ===
'wrld_27c7e6b2-d938-447e-a270-3d1a873e2cf3'
) {
activityType = ActivityType.Watching;
appId = '1095440531821170820';
@@ -291,24 +334,54 @@ export const useDiscordPresenceSettingsStore = defineStore(
}
}
if (gameLogStore.nowPlaying.name) {
L.worldName = gameLogStore.nowPlaying.name;
details = gameLogStore.nowPlaying.name;
}
if (gameLogStore.nowPlaying.playing) {
Discord.SetTimestamps(
gameLogStore.nowPlaying.startTime * 1000,
startTime = gameLogStore.nowPlaying.startTime * 1000;
endTime =
(gameLogStore.nowPlaying.startTime +
gameLogStore.nowPlaying.length) *
1000
);
1000;
}
} else if (!state.discordHideImage && L.thumbnailImageUrl) {
bigIcon = L.thumbnailImageUrl;
} else if (
!state.discordHideImage &&
state.lastLocationDetails.thumbnailImageUrl
) {
bigIcon = state.lastLocationDetails.thumbnailImageUrl;
}
if (hidePrivate) {
partyId = '';
partySize = 0;
partyMaxSize = 0;
buttonText = '';
buttonUrl = '';
stateUrl = '';
details = 'Private';
stateText = '';
startTime = 0;
endTime = 0;
appId = '883308884863901717'; // default VRChat app id
activityType = ActivityType.Playing;
}
if (details.length < 2) {
// 글자 수가 짧으면 업데이트가 안된다..
details += '\uFFA0'.repeat(2 - details.length);
}
Discord.SetAssets(
details, // main text
stateText, // secondary text
stateUrl, // state url
bigIcon, // big icon
'Powered by VRCX', // big icon hover text
L.statusImage, // small icon
L.statusName, // small icon hover text
statusImage, // small icon
statusName, // small icon hover text
startTime,
endTime,
partyId, // party id
partySize, // party size
partyMaxSize, // party max size
@@ -317,19 +390,6 @@ export const useDiscordPresenceSettingsStore = defineStore(
appId, // app id
activityType // activity type
);
// NOTE
// 글자 수가 짧으면 업데이트가 안된다..
if (L.worldName.length < 2) {
L.worldName += '\uFFA0'.repeat(2 - L.worldName.length);
}
if (hidePrivate) {
Discord.SetText('Private', '');
Discord.SetTimestamps(0, 0);
} else if (state.discordInstance) {
Discord.SetText(L.worldName, L.accessName);
} else {
Discord.SetText(L.worldName, '');
}
}
async function setIsDiscordActive(active) {
@@ -339,7 +399,7 @@ export const useDiscordPresenceSettingsStore = defineStore(
}
async function saveDiscordOption(configLabel = '') {
locationStore.lastLocation$.tag = '';
state.lastLocationDetails.tag = '';
updateLoopStore.nextDiscordUpdate = 3;
updateDiscord();
}

View File

@@ -56,6 +56,13 @@ export const useUpdateLoopStore = defineStore('UpdateLoop', () => {
}
});
const nextDiscordUpdate = computed({
get: () => state.nextDiscordUpdate,
set: (value) => {
state.nextDiscordUpdate = value;
}
});
async function updateLoop() {
const authStore = useAuthStore();
const userStore = useUserStore();
@@ -158,6 +165,7 @@ export const useUpdateLoopStore = defineStore('UpdateLoop', () => {
state,
nextGroupInstanceRefresh,
nextCurrentUserRefresh,
nextDiscordUpdate,
updateLoop
};
});

View File

@@ -3,6 +3,7 @@ import { BaseWorld } from '../common';
// API functions
export type GetWorld = (params: { worldId: string }) => Promise<{
json: GetWorldResponse;
ref: any;
params: { worldId: string };
}>;

View File

@@ -123,15 +123,16 @@ declare global {
};
const Discord: {
SetTimestamps(
startTimestamp: number,
endTimestamp: number
): Promise<void>;
SetAssets(
details: string,
state: string,
stateUrl: string,
bigIcon: string,
bigIconText: string,
smallIcon: string,
smallIconText: string,
startTime: number,
endTime: number,
partyId: string,
partySize: number,
partyMaxSize: number,
@@ -140,7 +141,6 @@ declare global {
appId: string,
activityType: number
): Promise<void>;
SetText(details: string, state: string): Promise<void>;
SetActive(active: boolean): Promise<boolean>;
};