mirror of
https://github.com/vrcx-team/VRCX.git
synced 2026-04-06 00:32:02 +02:00
inventory and prop support
This commit is contained in:
@@ -21,6 +21,8 @@ import inviteMessagesRequest from './inviteMessages';
|
||||
import imageRequest from './image';
|
||||
import miscRequest from './misc';
|
||||
import groupRequest from './group';
|
||||
import inventoryRequest from './inventory';
|
||||
import propRequest from './prop';
|
||||
|
||||
window.request = {
|
||||
userRequest,
|
||||
@@ -37,7 +39,9 @@ window.request = {
|
||||
inviteMessagesRequest,
|
||||
imageRequest,
|
||||
miscRequest,
|
||||
groupRequest
|
||||
groupRequest,
|
||||
inventoryRequest,
|
||||
propRequest
|
||||
};
|
||||
|
||||
export {
|
||||
@@ -55,5 +59,7 @@ export {
|
||||
inviteMessagesRequest,
|
||||
imageRequest,
|
||||
miscRequest,
|
||||
groupRequest
|
||||
groupRequest,
|
||||
inventoryRequest,
|
||||
propRequest
|
||||
};
|
||||
|
||||
74
src/api/inventory.js
Normal file
74
src/api/inventory.js
Normal file
@@ -0,0 +1,74 @@
|
||||
const inventoryReq = {
|
||||
/**
|
||||
* @param {{ inventoryId: string }} params
|
||||
* @returns {Promise<{json: any, params}>}
|
||||
*/
|
||||
getInventoryItem(params) {
|
||||
return window.API.call(`inventory/${params.inventoryId}`, {
|
||||
method: 'GET',
|
||||
params
|
||||
}).then((json) => {
|
||||
const args = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
return args;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {{ n: number, offset: number, order: string, types: string }} params
|
||||
* @returns {Promise<{json: any, params}>}
|
||||
*/
|
||||
getInventoryItems(params) {
|
||||
return window.API.call('inventory', {
|
||||
method: 'GET',
|
||||
params
|
||||
}).then((json) => {
|
||||
const args = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
return args;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {{ inventoryId: string }} params
|
||||
* @returns {Promise<{json: any, params}>}
|
||||
*/
|
||||
consumeInventoryBundle(params) {
|
||||
return window.API.call(`inventory/${params.inventoryId}/consume`, {
|
||||
method: 'PUT',
|
||||
params
|
||||
}).then((json) => {
|
||||
const args = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
return args;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {{ inventoryTemplateId: string }} params
|
||||
* @returns {Promise<{json: any, params}>}
|
||||
*/
|
||||
getInventoryTemplate(params) {
|
||||
return window.API.call(
|
||||
`inventory/template/${params.inventoryTemplateId}`,
|
||||
{
|
||||
method: 'GET',
|
||||
params
|
||||
}
|
||||
).then((json) => {
|
||||
const args = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
return args;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default inventoryReq;
|
||||
20
src/api/prop.js
Normal file
20
src/api/prop.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const propReq = {
|
||||
/**
|
||||
* @param {{ propId: string }} params
|
||||
* @returns {Promise<{json: any, params}>}
|
||||
*/
|
||||
getProp(params) {
|
||||
return window.API.call(`props/${params.propId}`, {
|
||||
method: 'GET',
|
||||
params
|
||||
}).then((json) => {
|
||||
const args = {
|
||||
json,
|
||||
params
|
||||
};
|
||||
return args;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default propReq;
|
||||
10
src/app.js
10
src/app.js
@@ -153,6 +153,7 @@ import _languages from './classes/languages.js';
|
||||
import _groups from './classes/groups.js';
|
||||
import _vrcRegistry from './classes/vrcRegistry.js';
|
||||
import _restoreFriendOrder from './classes/restoreFriendOrder.js';
|
||||
import _inventory from './classes/inventory.js';
|
||||
|
||||
import { userNotes } from './classes/userNotes.js';
|
||||
|
||||
@@ -244,7 +245,8 @@ console.log(`isLinux: ${LINUX}`);
|
||||
languages: new _languages($app, API, $t),
|
||||
groups: new _groups($app, API, $t),
|
||||
vrcRegistry: new _vrcRegistry($app, API, $t),
|
||||
restoreFriendOrder: new _restoreFriendOrder($app, API, $t)
|
||||
restoreFriendOrder: new _restoreFriendOrder($app, API, $t),
|
||||
inventory: new _inventory($app, API, $t)
|
||||
};
|
||||
|
||||
await configRepository.init();
|
||||
@@ -2014,6 +2016,7 @@ console.log(`isLinux: ${LINUX}`);
|
||||
this.cachedFavoriteGroups.clear();
|
||||
this.cachedFavoriteGroupsByTypeName.clear();
|
||||
this.currentUserGroups.clear();
|
||||
this.currentUserInventory.clear();
|
||||
this.queuedInstances.clear();
|
||||
this.favoriteFriendGroups = [];
|
||||
this.favoriteWorldGroups = [];
|
||||
@@ -9859,7 +9862,8 @@ console.log(`isLinux: ${LINUX}`);
|
||||
'stickers',
|
||||
'pedestals',
|
||||
'prints',
|
||||
'drones'
|
||||
'drones',
|
||||
'items'
|
||||
];
|
||||
|
||||
$app.methods.createNewInstance = async function (worldId = '', options) {
|
||||
@@ -10803,6 +10807,7 @@ console.log(`isLinux: ${LINUX}`);
|
||||
$app.data.galleryDialogEmojisLoading = false;
|
||||
$app.data.galleryDialogStickersLoading = false;
|
||||
$app.data.galleryDialogPrintsLoading = false;
|
||||
$app.data.galleryDialogInventoryLoading = false;
|
||||
|
||||
API.$on('LOGIN', function () {
|
||||
$app.galleryTable = [];
|
||||
@@ -10815,6 +10820,7 @@ console.log(`isLinux: ${LINUX}`);
|
||||
this.refreshEmojiTable();
|
||||
this.refreshStickerTable();
|
||||
this.refreshPrintTable();
|
||||
this.getInventory();
|
||||
workerTimers.setTimeout(() => this.setGalleryTab(pageNum), 100);
|
||||
};
|
||||
|
||||
|
||||
55
src/classes/inventory.js
Normal file
55
src/classes/inventory.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import * as workerTimers from 'worker-timers';
|
||||
import configRepository from '../service/config.js';
|
||||
import database from '../service/database.js';
|
||||
import { baseClass, $app, API, $t, $utils } from './baseClass.js';
|
||||
import { inventoryRequest } from '../api';
|
||||
|
||||
export default class extends baseClass {
|
||||
constructor(_app, _API, _t) {
|
||||
super(_app, _API, _t);
|
||||
}
|
||||
|
||||
init() {
|
||||
API.currentUserInventory = new Map();
|
||||
API.$on('LOGIN', function () {
|
||||
API.currentUserInventory.clear();
|
||||
});
|
||||
}
|
||||
|
||||
_data = {
|
||||
inventoryTable: []
|
||||
};
|
||||
|
||||
_methods = {
|
||||
async getInventory() {
|
||||
this.inventoryTable = [];
|
||||
API.currentUserInventory.clear();
|
||||
var params = {
|
||||
n: 100,
|
||||
offset: 0,
|
||||
order: 'newest'
|
||||
};
|
||||
this.galleryDialogInventoryLoading = true;
|
||||
try {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
params.offset = i * params.n;
|
||||
const args =
|
||||
await inventoryRequest.getInventoryItems(params);
|
||||
for (const item of args.json.data) {
|
||||
API.currentUserInventory.set(item.id, item);
|
||||
if (!item.flags.includes('ugc')) {
|
||||
this.inventoryTable.push(item);
|
||||
}
|
||||
}
|
||||
if (args.json.data.length === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching inventory items:', error);
|
||||
} finally {
|
||||
this.galleryDialogInventoryLoading = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -559,6 +559,15 @@ export default class extends baseClass {
|
||||
// on avatar gallery image upload
|
||||
} else if (contentType === 'invitePhoto') {
|
||||
// on uploading invite photo
|
||||
} else if (contentType === 'inventory') {
|
||||
if (
|
||||
$app.galleryDialogVisible &&
|
||||
!$app.galleryDialogInventoryLoading
|
||||
) {
|
||||
$app.getInventory();
|
||||
}
|
||||
// on consuming a bundle
|
||||
// {contentType: 'inventory', itemId: 'inv_', itemType: 'prop', actionType: 'add'}
|
||||
} else if (!contentType) {
|
||||
console.log(
|
||||
'content-refresh without contentType',
|
||||
|
||||
@@ -444,6 +444,48 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane v-loading="galleryDialogInventoryLoading" lazy>
|
||||
<span slot="label">
|
||||
{{ t('dialog.gallery_icons.inventory') }}
|
||||
<span style="color: #909399; font-size: 12px; margin-left: 5px"> {{ inventoryTable.length }} </span>
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
<div
|
||||
class="x-friend-item"
|
||||
v-for="item in inventoryTable"
|
||||
:key="item.id"
|
||||
style="display: inline-block; margin-top: 10px; width: unset; cursor: default">
|
||||
<div class="vrcplus-icon" style="overflow: hidden; cursor: default">
|
||||
<img class="avatar" v-lazy="item.imageUrl" />
|
||||
</div>
|
||||
<div style="margin-top: 5px; width: 208px">
|
||||
<span class="x-ellipsis" v-text="item.name" style="display: block"></span>
|
||||
<span
|
||||
v-if="item.description"
|
||||
class="x-ellipsis"
|
||||
v-text="item.description"
|
||||
style="display: block"></span>
|
||||
<span v-else style="display: block"> </span>
|
||||
<span
|
||||
class="x-ellipsis"
|
||||
style="color: #909399; font-family: monospace; font-size: 11px; display: block">
|
||||
{{ item.created_at | formatDate('long') }}
|
||||
</span>
|
||||
<span v-text="item.itemType" style="display: block"></span>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="item.itemType === 'bundle'"
|
||||
type="default"
|
||||
@click="consumeInventoryBundle(item.id)"
|
||||
size="mini"
|
||||
icon="el-icon-plus"
|
||||
circle>
|
||||
{{ t('dialog.gallery_icons.consume_bundle') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</safe-dialog>
|
||||
</template>
|
||||
@@ -451,7 +493,7 @@
|
||||
<script setup>
|
||||
import { getCurrentInstance, inject, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n-bridge';
|
||||
import { userRequest, vrcPlusIconRequest, vrcPlusImageRequest, miscRequest } from '../../../api';
|
||||
import { userRequest, vrcPlusIconRequest, vrcPlusImageRequest, miscRequest, inventoryRequest } from '../../../api';
|
||||
import { extractFileId } from '../../../composables/shared/utils';
|
||||
import { emojiAnimationStyleList, emojiAnimationStyleUrl } from '../../../composables/user/constants/emoji';
|
||||
import { getPrintFileName } from '../../../composables/user/utils';
|
||||
@@ -490,6 +532,10 @@
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
galleryDialogInventoryLoading: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
galleryTable: {
|
||||
type: Array,
|
||||
required: true
|
||||
@@ -518,6 +564,10 @@
|
||||
printTable: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
inventoryTable: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1025,4 +1075,27 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function consumeInventoryBundle(inventoryId) {
|
||||
try {
|
||||
const args = await inventoryRequest.consumeInventoryBundle({
|
||||
inventoryId
|
||||
});
|
||||
API.currentUserInventory.delete(inventoryId);
|
||||
const array = props.inventoryTable;
|
||||
const { length } = array;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
if (inventoryId === array[i].id) {
|
||||
array.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.getInventory();
|
||||
} catch (error) {
|
||||
console.error('Error consuming inventory bundle:', error);
|
||||
}
|
||||
// errors: []
|
||||
// inventoryItems : []
|
||||
// inventoryItemsCreated: 0
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1798,6 +1798,7 @@
|
||||
:gallery-dialog-emojis-loading="galleryDialogEmojisLoading"
|
||||
:gallery-dialog-stickers-loading="galleryDialogStickersLoading"
|
||||
:gallery-dialog-prints-loading="galleryDialogPrintsLoading"
|
||||
:gallery-dialog-inventory-loading="galleryDialogInventoryLoading"
|
||||
:gallery-table="galleryTable"
|
||||
:VRCPlusIconsTable="VRCPlusIconsTable"
|
||||
:emoji-table="emojiTable"
|
||||
@@ -1805,6 +1806,7 @@
|
||||
:print-upload-note="printUploadNote"
|
||||
:print-crop-border="printCropBorder"
|
||||
:print-table="printTable"
|
||||
:inventory-table="inventoryTable"
|
||||
@refreshGalleryTable="refreshGalleryTable"
|
||||
@refreshVRCPlusIconsTable="refreshVRCPlusIconsTable"
|
||||
@refreshStickerTable="refreshStickerTable"
|
||||
@@ -2002,6 +2004,10 @@
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
galleryDialogInventoryLoading: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
galleryTable: {
|
||||
type: Array,
|
||||
required: true
|
||||
@@ -2030,6 +2036,10 @@
|
||||
printTable: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
inventoryTable: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1444,6 +1444,7 @@
|
||||
"emojis": "Emojis",
|
||||
"stickers": "Stickers",
|
||||
"prints": "Prints",
|
||||
"inventory": "Inventory",
|
||||
"refresh": "Refresh",
|
||||
"upload": "Upload",
|
||||
"clear": "Clear",
|
||||
@@ -1454,7 +1455,8 @@
|
||||
"emoji_loop_pingpong": "Loop PingPong",
|
||||
"flipbook_info": "Select a 1024x1024 PNG spritesheet to use as an animated emoji, available frame grid sizes: 4, 16 or 64 (max FPS 64, max frames 64)",
|
||||
"note": "Note",
|
||||
"crop_print_border": "Crop Print Border"
|
||||
"crop_print_border": "Crop Print Border",
|
||||
"consume_bundle": "Consume"
|
||||
},
|
||||
"change_content_image": {
|
||||
"avatar": "Change Avatar Image",
|
||||
|
||||
@@ -88,6 +88,7 @@ mixin dialogs
|
||||
:galleryDialogEmojisLoading='galleryDialogEmojisLoading'
|
||||
:galleryDialogStickersLoading='galleryDialogStickersLoading'
|
||||
:galleryDialogPrintsLoading='galleryDialogPrintsLoading'
|
||||
:galleryDialogInventoryLoading='galleryDialogInventoryLoading'
|
||||
:galleryTable='galleryTable'
|
||||
:VRCPlusIconsTable='VRCPlusIconsTable'
|
||||
:emojiTable='emojiTable'
|
||||
@@ -95,6 +96,7 @@ mixin dialogs
|
||||
:printUploadNote='printUploadNote'
|
||||
:printCropBorder='printCropBorder'
|
||||
:printTable='printTable'
|
||||
:inventoryTable='inventoryTable'
|
||||
@refreshGalleryTable='refreshGalleryTable'
|
||||
@refreshEmojiTable='refreshEmojiTable'
|
||||
@refreshStickerTable='refreshStickerTable'
|
||||
|
||||
Reference in New Issue
Block a user