mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-18 22:33:50 +02:00
Add Avatar Wear Timers (#1086)
* Update avatar history table * Tracking time when swapping avis * Time spent now visible on application * Added wear time tracking on game open/close * Update avatar history table * Tracking time when swapping avis * Time spent now visible on application * Added wear time tracking on game open/close * Adjusted "ON CONFLICT" query * Removed unneccesary "previousAvatar" parameter
This commit is contained in:
29
src/app.js
29
src/app.js
@@ -3800,6 +3800,14 @@ console.log(`isLinux: ${LINUX}`);
|
||||
this.nextDiscordUpdate = 0;
|
||||
console.log(new Date(), 'isGameRunning', isGameRunning);
|
||||
}
|
||||
|
||||
if (isGameRunning) {
|
||||
API.currentUser.$previousAvatarSwapTime = Date.now();
|
||||
} else if (API.currentUser.$previousAvatarSwapTime) {
|
||||
this.addAvatarWearTime(API.currentUser.currentAvatar);
|
||||
API.currentUser.$previousAvatarSwapTime = '';
|
||||
}
|
||||
|
||||
if (isSteamVRRunning !== this.isSteamVRRunning) {
|
||||
this.isSteamVRRunning = isSteamVRRunning;
|
||||
console.log('isSteamVRRunning:', isSteamVRRunning);
|
||||
@@ -12090,6 +12098,7 @@ console.log(`isLinux: ${LINUX}`);
|
||||
treeData: [],
|
||||
bundleSizes: [],
|
||||
platformInfo: {},
|
||||
timeSpent: 0,
|
||||
lastUpdated: '',
|
||||
inCache: false,
|
||||
cacheSize: 0,
|
||||
@@ -12140,6 +12149,7 @@ console.log(`isLinux: ${LINUX}`);
|
||||
D.lastUpdated = '';
|
||||
D.bundleSizes = [];
|
||||
D.platformInfo = {};
|
||||
D.timeSpent = 0;
|
||||
D.isFavorite =
|
||||
API.cachedFavoritesByObjectId.has(avatarId) ||
|
||||
(this.isLocalUserVrcplusSupporter() &&
|
||||
@@ -12158,6 +12168,9 @@ console.log(`isLinux: ${LINUX}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
database.getAvatarTimeSpent(avatarId).then((aviTime) => {
|
||||
D.timeSpent = aviTime.timeSpent;
|
||||
});
|
||||
API.getAvatar({ avatarId })
|
||||
.then((args) => {
|
||||
var { ref } = args;
|
||||
@@ -19861,24 +19874,32 @@ console.log(`isLinux: ${LINUX}`);
|
||||
$app.methods.addAvatarToHistory = function (avatarId) {
|
||||
API.getAvatar({ avatarId }).then((args) => {
|
||||
var { ref } = args;
|
||||
|
||||
database.addAvatarToCache(ref);
|
||||
database.addAvatarToHistory(ref.id);
|
||||
|
||||
if (ref.authorId === API.currentUser.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
var historyArray = this.avatarHistoryArray;
|
||||
for (var i = 0; i < historyArray.length; ++i) {
|
||||
if (historyArray[i].id === ref.id) {
|
||||
historyArray.splice(i, 1);
|
||||
}
|
||||
}
|
||||
this.avatarHistoryArray.unshift(ref);
|
||||
database.addAvatarToCache(ref);
|
||||
|
||||
this.avatarHistoryArray.unshift(ref);
|
||||
this.avatarHistory.delete(ref.id);
|
||||
this.avatarHistory.add(ref.id);
|
||||
database.addAvatarToHistory(ref.id);
|
||||
});
|
||||
};
|
||||
|
||||
$app.methods.addAvatarWearTime = function (avatar) {
|
||||
const timeSpent = Date.now() - API.currentUser.$previousAvatarSwapTime;
|
||||
database.addAvatarTimeSpent(avatar, timeSpent);
|
||||
};
|
||||
|
||||
$app.methods.promptClearAvatarHistory = function () {
|
||||
this.$confirm('Continue? Clear Avatar History', 'Confirm', {
|
||||
confirmButtonText: 'Confirm',
|
||||
@@ -19904,7 +19925,7 @@ console.log(`isLinux: ${LINUX}`);
|
||||
);
|
||||
|
||||
$app.methods.updateDatabaseVersion = async function () {
|
||||
var databaseVersion = 11;
|
||||
var databaseVersion = 12;
|
||||
if (this.databaseVersion < databaseVersion) {
|
||||
if (this.databaseVersion) {
|
||||
var msgBox = this.$message({
|
||||
|
||||
@@ -106,7 +106,6 @@ export default class extends baseClass {
|
||||
travelingToInstance = json.presence.travelingToInstance;
|
||||
travelingToWorld = json.presence.travelingToWorld;
|
||||
}
|
||||
|
||||
this.applyUser({
|
||||
allowAvatarCopying: json.allowAvatarCopying,
|
||||
badges: json.badges,
|
||||
@@ -166,6 +165,8 @@ export default class extends baseClass {
|
||||
if (this.isLoggedIn) {
|
||||
if (json.currentAvatar !== ref.currentAvatar) {
|
||||
$app.addAvatarToHistory(json.currentAvatar);
|
||||
$app.addAvatarWearTime(ref.currentAvatar);
|
||||
this.currentUser.$previousAvatarSwapTime = Date.now();
|
||||
}
|
||||
Object.assign(ref, json);
|
||||
if (ref.homeLocation !== ref.$homeLocation.tag) {
|
||||
@@ -277,6 +278,7 @@ export default class extends baseClass {
|
||||
$offline_for: '',
|
||||
$location_at: Date.now(),
|
||||
$travelingToTime: Date.now(),
|
||||
$previousAvatarSwapTime: Date.now(),
|
||||
$homeLocation: {},
|
||||
$isVRCPlus: false,
|
||||
$isModerator: false,
|
||||
|
||||
@@ -927,6 +927,7 @@
|
||||
"last_updated": "Last Updated",
|
||||
"version": "Version",
|
||||
"platform": "Platform",
|
||||
"time_spent": "Time Spent",
|
||||
"memo": "Memo",
|
||||
"memo_placeholder": "Click to add a memo"
|
||||
},
|
||||
|
||||
@@ -848,6 +848,7 @@
|
||||
"last_updated": "Actualizado por última vez",
|
||||
"version": "Versión",
|
||||
"platform": "Plataforma",
|
||||
"time_spent": "Tiempo invertido",
|
||||
"memo": "Nota de VRCX",
|
||||
"memo_placeholder": "Haga clic aquí para añadir una nota"
|
||||
},
|
||||
|
||||
@@ -923,6 +923,7 @@
|
||||
"last_updated": "Dernière mise à jour",
|
||||
"version": "Version",
|
||||
"platform": "Plateforme",
|
||||
"time_spent": "Temps passé",
|
||||
"memo": "Mémo",
|
||||
"memo_placeholder": "Cliquez pour ajouter un mémo"
|
||||
},
|
||||
|
||||
@@ -808,6 +808,7 @@
|
||||
"last_updated": "Last Updated",
|
||||
"version": "Verzió",
|
||||
"platform": "Platform",
|
||||
"time_spent": "Time Spent",
|
||||
"memo": "Memo",
|
||||
"memo_placeholder": "Click to add a memo"
|
||||
},
|
||||
|
||||
@@ -831,6 +831,7 @@
|
||||
"last_updated": "最終更新日時",
|
||||
"version": "バージョン",
|
||||
"platform": "プラットフォーム",
|
||||
"time_spent": "過ごした時間",
|
||||
"memo": "メモ (VRCX)",
|
||||
"memo_placeholder": "クリックしてメモを追加"
|
||||
},
|
||||
|
||||
@@ -808,6 +808,7 @@
|
||||
"last_updated": "마지막 업데이트",
|
||||
"version": "버전",
|
||||
"platform": "플랫폼",
|
||||
"time_spent": "방문 시간",
|
||||
"memo": "VRCX 메모",
|
||||
"memo_placeholder": "-"
|
||||
},
|
||||
|
||||
@@ -808,6 +808,7 @@
|
||||
"last_updated": "Ostatnia aktualizacja",
|
||||
"version": "Wersja",
|
||||
"platform": "Platforma",
|
||||
"time_spent": "Spędzony czas",
|
||||
"memo": "Notatka VRCX",
|
||||
"memo_placeholder": "Kliknij, aby dodać notatkę VRCX"
|
||||
},
|
||||
|
||||
@@ -808,6 +808,7 @@
|
||||
"last_updated": "Última Atualização",
|
||||
"version": "Versão",
|
||||
"platform": "Plataforma",
|
||||
"time_spent": "Tempo Gasto",
|
||||
"memo": "Memo",
|
||||
"memo_placeholder": "Click to add a memo"
|
||||
},
|
||||
|
||||
@@ -854,6 +854,7 @@
|
||||
"last_updated": "Последнее обновление",
|
||||
"version": "Версия",
|
||||
"platform": "Платформа",
|
||||
"time_spent": "Проведенное время",
|
||||
"memo": "Заметка VRCX",
|
||||
"memo_placeholder": "Нажмите, чтобы добавить заметку"
|
||||
},
|
||||
|
||||
@@ -808,6 +808,7 @@
|
||||
"last_updated": "Lần cập nhật cuối",
|
||||
"version": "Phiên bản",
|
||||
"platform": "Nền tảng",
|
||||
"time_spent": "Thời gian đã ở",
|
||||
"memo": "Ghi nhớ",
|
||||
"memo_placeholder": "Bấm để tạo ghi nhớ"
|
||||
},
|
||||
|
||||
@@ -856,6 +856,7 @@
|
||||
"last_updated": "最后更新",
|
||||
"version": "版本",
|
||||
"platform": "平台",
|
||||
"time_spent": "总停留时长",
|
||||
"memo": "本地备注",
|
||||
"memo_placeholder": "点击添加备注"
|
||||
},
|
||||
|
||||
@@ -856,6 +856,7 @@
|
||||
"last_updated": "最後更新",
|
||||
"version": "版本",
|
||||
"platform": "平台",
|
||||
"time_spent": "停留時長",
|
||||
"memo": "備註",
|
||||
"memo_placeholder": "點擊新增備忘錄"
|
||||
},
|
||||
|
||||
@@ -101,6 +101,11 @@ mixin avatarDialog()
|
||||
span.name {{ $t('dialog.avatar.info.version') }}
|
||||
span.extra(v-if="avatarDialog.ref.version !== 0" v-text="avatarDialog.ref.version")
|
||||
span.extra(v-else) -
|
||||
.x-friend-item(style="cursor:default")
|
||||
.detail
|
||||
span.name {{ $t('dialog.avatar.info.time_spent') }}
|
||||
span.extra(v-if="avatarDialog.timeSpent === 0") -
|
||||
span.extra(v-else) {{ timeToText(avatarDialog.timeSpent) }}
|
||||
.x-friend-item(style="width:100%;cursor:default")
|
||||
.detail
|
||||
span.name {{ $t('dialog.avatar.info.platform') }}
|
||||
|
||||
@@ -40,7 +40,7 @@ class Database {
|
||||
`CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_moderation (user_id TEXT PRIMARY KEY, updated_at TEXT, display_name TEXT, block INTEGER, mute INTEGER)`
|
||||
);
|
||||
await sqliteService.executeNonQuery(
|
||||
`CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_avatar_history (avatar_id TEXT PRIMARY KEY, created_at TEXT)`
|
||||
`CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_avatar_history (avatar_id TEXT PRIMARY KEY, created_at TEXT, time INTEGER)`
|
||||
);
|
||||
await sqliteService.executeNonQuery(
|
||||
`CREATE TABLE IF NOT EXISTS memos (user_id TEXT PRIMARY KEY, edited_at TEXT, memo TEXT)`
|
||||
@@ -2189,7 +2189,13 @@ class Database {
|
||||
|
||||
addAvatarToHistory(avatarId) {
|
||||
sqliteService.executeNonQuery(
|
||||
`INSERT OR REPLACE INTO ${Database.userPrefix}_avatar_history (avatar_id, created_at) VALUES (@avatar_id, @created_at)`,
|
||||
`UPDATE ${Database.userPrefix}_avatar_history
|
||||
SET created_at = @created_at, time = COALESCE(time, 0)
|
||||
WHERE avatar_id = @avatar_id;
|
||||
|
||||
INSERT INTO ${Database.userPrefix}_avatar_history (avatar_id, created_at, time)
|
||||
SELECT @avatar_id, @created_at, 0
|
||||
WHERE NOT EXISTS (SELECT * FROM ${Database.userPrefix}_avatar_history WHERE avatar_id = @avatar_id)`,
|
||||
{
|
||||
'@avatar_id': avatarId,
|
||||
'@created_at': new Date().toJSON()
|
||||
@@ -2197,21 +2203,49 @@ class Database {
|
||||
);
|
||||
}
|
||||
|
||||
async getAvatarTimeSpent(avatarId) {
|
||||
var ref = {
|
||||
timeSpent: 0,
|
||||
avatarId
|
||||
};
|
||||
await sqliteService.execute(
|
||||
(row) => {
|
||||
ref.timeSpent = row[0];
|
||||
},
|
||||
`SELECT time FROM ${Database.userPrefix}_avatar_history WHERE avatar_id = @avatarId`,
|
||||
{
|
||||
'@avatarId': avatarId
|
||||
}
|
||||
);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
addAvatarTimeSpent(avatarId, timeSpent) {
|
||||
sqliteService.executeNonQuery(
|
||||
`UPDATE ${Database.userPrefix}_avatar_history SET time = time + @timeSpent WHERE avatar_id = @avatarId`,
|
||||
{
|
||||
'@avatarId': avatarId,
|
||||
'@timeSpent': timeSpent
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async getAvatarHistory(currentUserId, limit = 100) {
|
||||
var data = [];
|
||||
await sqliteService.execute((dbRow) => {
|
||||
var row = {
|
||||
id: dbRow[0],
|
||||
authorId: dbRow[4],
|
||||
authorName: dbRow[5],
|
||||
created_at: dbRow[6],
|
||||
description: dbRow[7],
|
||||
imageUrl: dbRow[8],
|
||||
name: dbRow[9],
|
||||
releaseStatus: dbRow[10],
|
||||
thumbnailImageUrl: dbRow[11],
|
||||
updated_at: dbRow[12],
|
||||
version: dbRow[13]
|
||||
authorId: dbRow[5],
|
||||
authorName: dbRow[6],
|
||||
created_at: dbRow[7],
|
||||
description: dbRow[8],
|
||||
imageUrl: dbRow[9],
|
||||
name: dbRow[10],
|
||||
releaseStatus: dbRow[11],
|
||||
thumbnailImageUrl: dbRow[12],
|
||||
updated_at: dbRow[13],
|
||||
version: dbRow[14]
|
||||
};
|
||||
data.push(row);
|
||||
}, `SELECT * FROM ${Database.userPrefix}_avatar_history INNER JOIN cache_avatar ON cache_avatar.id = ${Database.userPrefix}_avatar_history.avatar_id WHERE author_id != "${currentUserId}" ORDER BY ${Database.userPrefix}_avatar_history.created_at DESC LIMIT ${limit}`);
|
||||
@@ -2617,6 +2651,7 @@ class Database {
|
||||
// if (version === 0) {
|
||||
await this.updateTableForGroupNames();
|
||||
await this.addFriendLogFriendNumber();
|
||||
await this.updateTableForAvatarHistory();
|
||||
// }
|
||||
// await sqliteService.executeNonQuery('PRAGMA user_version = 1');
|
||||
}
|
||||
@@ -2632,7 +2667,7 @@ class Database {
|
||||
`ALTER TABLE ${tableName} ADD friend_number INTEGER DEFAULT 0`
|
||||
);
|
||||
} catch (e) {
|
||||
e = e.toString();
|
||||
e = e.toString();
|
||||
if (e.indexOf('duplicate column name') === -1) {
|
||||
console.error(e);
|
||||
}
|
||||
@@ -2651,7 +2686,7 @@ class Database {
|
||||
`ALTER TABLE ${tableName} ADD group_name TEXT DEFAULT ''`
|
||||
);
|
||||
} catch (e) {
|
||||
e = e.toString();
|
||||
e = e.toString();
|
||||
if (e.indexOf('duplicate column name') === -1) {
|
||||
console.error(e);
|
||||
}
|
||||
@@ -2670,6 +2705,17 @@ class Database {
|
||||
}
|
||||
}
|
||||
|
||||
async updateTableForAvatarHistory() {
|
||||
await sqliteService.execute((dbRow) => {
|
||||
const columnExists = dbRow.some((row) => row.name === 'time');
|
||||
if (!columnExists) {
|
||||
sqliteService.executeNonQuery(
|
||||
`ALTER TABLE ${Database.userPrefix}_avatar_history ADD COLUMN 'time' INTEGER DEFAULT 0;`
|
||||
);
|
||||
}
|
||||
}, `PRAGMA table_info(${Database.userPrefix}_avatar_history);`);
|
||||
}
|
||||
|
||||
async fixCancelFriendRequestTypo() {
|
||||
await sqliteService.executeNonQuery(
|
||||
`UPDATE ${Database.userPrefix}_friend_log_history SET type = 'CancelFriendRequest' WHERE type = 'CancelFriendRequst'`
|
||||
@@ -2728,4 +2774,4 @@ class Database {
|
||||
var self = new Database();
|
||||
window.database = self;
|
||||
|
||||
export { self as default, Database };
|
||||
export { self as default, Database };
|
||||
|
||||
Reference in New Issue
Block a user