Merge pull request #521 from kasenvr/feature/inventory-app

Feature/inventory app
This commit is contained in:
kasenvr 2020-07-23 17:15:37 -04:00 committed by GitHub
commit d585b068b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 16377 additions and 0 deletions

20
scripts/system/inventory/.gitignore vendored Normal file
View file

@ -0,0 +1,20 @@
.DS_Store
node_modules
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View file

@ -0,0 +1,24 @@
# inventory
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

View file

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

View file

@ -0,0 +1 @@
.draggable-card{background-color:#272727;margin:5px 0}.draggable-card .handle{width:40px!important}.top-level-folder{background-color:#272727}.top-level-folder .v-list-group__header__prepend-icon{background-color:rgba(0,0,0,.3);width:50px;height:50px;margin:5px 5px 7px 0!important;padding:5px 18px 5px 8px}.top-level-folder .handle{width:40px!important}.top-level-folder .folder-icon{margin-right:10px}.top-level-folder .folder-button{font-size:.795rem!important}.v-list-group .column-item{max-width:100%!important;margin-top:5px;margin-bottom:5px}.v-list-group .draggable-card{background-color:rgba(0,0,0,.3);padding-right:16px;padding-left:0!important}.v-list-group .draggable-card .handle{margin-right:16px}.app-version{text-align:center;color:hsla(0,0%,100%,.6);font-weight:lighter}.handle{background-color:rgba(0,0,0,.3)}.inventoryApp::-webkit-scrollbar{width:0!important}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -0,0 +1 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=favicon.ico><title>Inventory</title><link rel=stylesheet href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900"><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css><link href=css/app.a93e8b1f.css rel=preload as=style><link href=css/chunk-vendors.8540aa41.css rel=preload as=style><link href=js/app.a3555a80.js rel=preload as=script><link href=js/chunk-vendors.a0f21a27.js rel=preload as=script><link href=css/chunk-vendors.8540aa41.css rel=stylesheet><link href=css/app.a93e8b1f.css rel=stylesheet></head><body><noscript><strong>We're sorry but Inventory doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.a0f21a27.js></script><script src=js/app.a3555a80.js></script></body></html>

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="#0c0" d="M17,14H19V17H22V19H19V22H17V19H14V17H17V14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.53C20.94,12.58 19.54,12 18,12A6,6 0 0,0 12,18C12,19.09 12.29,20.12 12.8,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 552 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M16.5,12C19,12 21,14 21,16.5C21,17.38 20.75,18.21 20.31,18.9L23.39,22L22,23.39L18.88,20.32C18.19,20.75 17.37,21 16.5,21C14,21 12,19 12,16.5C12,14 14,12 16.5,12M16.5,14A2.5,2.5 0 0,0 14,16.5A2.5,2.5 0 0,0 16.5,19A2.5,2.5 0 0,0 19,16.5A2.5,2.5 0 0,0 16.5,14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.03C20.85,11.21 18.82,10 16.5,10A6.5,6.5 0 0,0 10,16.5C10,18.25 10.69,19.83 11.81,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 761 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="#0f0" d="M17,14H19V17H22V19H19V22H17V19H14V17H17V14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.53C20.94,12.58 19.54,12 18,12A6,6 0 0,0 12,18C12,19.09 12.29,20.12 12.8,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 552 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="white" d="M16.5,12C19,12 21,14 21,16.5C21,17.38 20.75,18.21 20.31,18.9L23.39,22L22,23.39L18.88,20.32C18.19,20.75 17.37,21 16.5,21C14,21 12,19 12,16.5C12,14 14,12 16.5,12M16.5,14A2.5,2.5 0 0,0 14,16.5A2.5,2.5 0 0,0 16.5,19A2.5,2.5 0 0,0 19,16.5A2.5,2.5 0 0,0 16.5,14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.03C20.85,11.21 18.82,10 16.5,10A6.5,6.5 0 0,0 10,16.5C10,18.25 10.69,19.83 11.81,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 775 B

View file

@ -0,0 +1,299 @@
//
// inventory.js
//
// Created by kasenvr@gmail.com on 2 Apr 2020
// Copyright 2020 Vircadia and contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/* global AvatarList Clipboard console Controller Entities location Messages MyAvatar Script ScriptDiscoveryService Settings
Tablet Vec3 Window */
(function () { // BEGIN LOCAL_SCOPE
"use strict";
var AppUi = Script.require('appUi');
var ui;
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
// VARIABLES
var inventoryDataSettingString = "inventoryApp.data";
var inventoryData;
var inventorySettingsString = "inventoryApp.settings";
var inventorySettings;
var RECEIVING_ITEM_QUEUE_LIMIT = 5;
var receivingItemQueue = [];
var NEARBY_USERS_SEARCH_RADIUS = 25;
// APP EVENT AND MESSAGING ROUTING
function onWebAppEventReceived(event) {
var eventJSON = JSON.parse(event);
if (eventJSON.app === "inventory") { // This is our web app!
// print("inventory.js received a web event: " + event);
if (eventJSON.command === "ready") {
initializeInventoryApp();
}
if (eventJSON.command === "web-to-script-inventory") {
receiveInventory(eventJSON.data);
}
if (eventJSON.command === "web-to-script-settings") {
receiveSettings(eventJSON.data);
}
if (eventJSON.command === "use-item") {
useItem(eventJSON.data);
}
if (eventJSON.command === "share-item") {
shareItem(eventJSON.data);
}
if (eventJSON.command === "web-to-script-request-nearby-users") {
sendNearbyUsers();
}
if (eventJSON.command === "web-to-script-request-receiving-item-queue") {
sendReceivingItemQueue();
}
if (eventJSON.command === "web-to-script-update-receiving-item-queue") {
updateReceivingItemQueue(eventJSON.data);
}
}
}
tablet.webEventReceived.connect(onWebAppEventReceived);
function sendToWeb(command, data) {
var dataToSend = {
"app": "inventory",
"command": command,
"data": data
};
tablet.emitScriptEvent(JSON.stringify(dataToSend));
}
var inventoryMessagesChannel = "com.vircadia.inventory";
function onMessageReceived(channel, message, sender, localOnly) {
if (channel === inventoryMessagesChannel) {
var messageJSON = JSON.parse(message);
// Window.alert("Passed 0 " + messageJSON.recipient + " vs " + MyAvatar.sessionUUID);
if (messageJSON.command === "share-item"
&& messageJSON.recipient === MyAvatar.sessionUUID) { // We are receiving an item.
// Window.alert("Passed 1 " + messageJSON.recipient + " vs " + MyAvatar.sessionUUID);
pushReceivedItemToQueue(sender, messageJSON.type, messageJSON.name, messageJSON.url);
}
}
// print("Message received:");
// print("- channel: " + channel);
// print("- message: " + message);
// print("- sender: " + sender);
// print("- localOnly: " + localOnly);
}
function sendMessage(dataToSend) {
Messages.sendMessage(inventoryMessagesChannel, JSON.stringify(dataToSend));
}
// END APP EVENT AND MESSAGING ROUTING
// SEND AND RECEIVE INVENTORY STATE
function receiveInventory(receivedInventoryData) {
inventoryData = receivedInventoryData;
saveInventory();
}
function sendInventory() {
sendToWeb("script-to-web-inventory", inventoryData);
}
// END SEND AND RECEIVE INVENTORY STATE
// SEND AND RECEIVE SETTINGS STATE
function receiveSettings(receivedSettingsData) {
inventorySettings = receivedSettingsData;
saveSettings();
}
function sendSettings() {
sendToWeb("script-to-web-settings", inventorySettings);
}
// END SEND AND RECEIVE SETTINGS STATE
function saveInventory() {
Settings.setValue(inventoryDataSettingString, inventoryData);
}
function loadInventory() {
inventoryData = Settings.getValue(inventoryDataSettingString);
}
function saveSettings() {
Settings.setValue(inventorySettingsString, inventorySettings);
}
function loadSettings() {
inventorySettings = Settings.getValue(inventorySettingsString);
}
function pushReceivedItemToQueue(senderUUID, type, name, url) {
console.info("Receiving an item:", name, "from:", senderUUID);
var getAvatarData = AvatarList.getAvatar(senderUUID);
var senderName = getAvatarData.sessionDisplayName;
var senderDistance = Vec3.distance(MyAvatar.position, getAvatarData.position);
var packageRequest = {
"senderUUID": senderUUID,
"senderName": senderName,
"senderDistance": senderDistance,
"data": {
"type": type,
"name": name,
"url": url
}
};
if (receivingItemQueue.length === RECEIVING_ITEM_QUEUE_LIMIT) {
receivingItemQueue = receivingItemQueue.slice(1, RECEIVING_ITEM_QUEUE_LIMIT);
}
receivingItemQueue.push(packageRequest);
ui.messagesWaiting(receivingItemQueue.length > 0);
}
function sendReceivingItemQueue() {
sendToWeb("script-to-web-receiving-item-queue", receivingItemQueue);
}
function updateReceivingItemQueue(data) {
receivingItemQueue = data;
ui.messagesWaiting(receivingItemQueue.length > 0);
}
function sendNearbyUsers() {
var nearbyUsers = AvatarList.getAvatarsInRange(MyAvatar.position, NEARBY_USERS_SEARCH_RADIUS);
var nearbyUsersToSend = [];
nearbyUsers.forEach(function(user) {
var objectToWrite;
var aviDetails = AvatarList.getAvatar(user);
var aviName = aviDetails.displayName;
var aviDistance = Vec3.distance(MyAvatar.position, aviDetails.position);
// Window.alert("aviName" + aviName + "user" + user + "MyAvatar.sessionUUID" + MyAvatar.sessionUUID);
if (user !== MyAvatar.sessionUUID
|| Controller.getValue(Controller.Hardware.Keyboard.Shift)) { // Don't add ourselves to the list!
objectToWrite = { "name": aviName, "distance": aviDistance, "uuid": user };
nearbyUsersToSend.push(objectToWrite);
}
});
sendToWeb("script-to-web-nearby-users", nearbyUsersToSend);
}
function useItem(item) {
//TODO: Add animation support for avatars...?
// Convert the item.type before checking it...
item.type = item.type.toUpperCase();
// Depending on the type, we decide how to load this item.
if (item.type === "SCRIPT") {
ScriptDiscoveryService.loadScript(item.url, true, false, false, true, false);
}
if (item.type === "MODEL") {
Entities.addEntity({
type: "Model",
position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1.5 })),
rotation: MyAvatar.orientation,
modelURL: item.url,
collisionless: true
});
}
if (item.type === "AVATAR") {
MyAvatar.useFullAvatarURL(item.url);
}
if (item.type === "PLACE") {
location.handleLookupString(item.url, true);
}
if (item.type === "JSON") {
var jsonToLoad = item.url;
if (jsonToLoad) {
if (Clipboard.importEntities(jsonToLoad)) {
Clipboard.pasteEntities(
Vec3.sum(
MyAvatar.position,
Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1.5 })
)
);
}
}
}
if (item.type === "UNKNOWN") {
// We don't know how to handle this yet.
Window.alert("Unknown item type, unable to use.");
}
}
function shareItem(data) {
data.command = "share-item";
sendMessage(data);
}
function initializeInventoryApp() {
sendSettings();
sendInventory();
sendReceivingItemQueue();
}
function onOpened() {
}
function onClosed() {
}
function startup() {
loadInventory();
loadSettings();
Messages.messageReceived.connect(onMessageReceived);
Messages.subscribe(inventoryMessagesChannel);
ui = new AppUi({
buttonName: "INVENTORY",
home: Script.resolvePath("index.html"),
graphicsDirectory: Script.resolvePath("./"), // Where your button icons are located
onOpened: onOpened,
onClosed: onClosed
});
}
startup();
Script.scriptEnding.connect(function () {
Messages.messageReceived.disconnect(onMessageReceived);
Messages.unsubscribe(inventoryMessagesChannel);
});
}()); // END LOCAL_SCOPE

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

13049
scripts/system/inventory/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,52 @@
{
"name": "Inventory",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@mdi/font": "^4.9.95",
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vuedraggable": "^2.24.0",
"vuetify": "^2.3.4",
"vuex": "^3.5.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.3.1",
"@vue/cli-plugin-eslint": "^4.3.1",
"@vue/cli-service": "^4.3.1",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"sass": "^1.26.10",
"sass-loader": "^8.0.0",
"vue-cli-plugin-vuetify": "^2.0.7",
"vue-template-compiler": "^2.6.11",
"vuetify-loader": "^1.6.0"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"ChromeAndroid > 55",
"Chrome > 55"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -0,0 +1,30 @@
<!--
//
// index.html
//
// Created by kasenvr@gmail.com on 7 Apr 2020
// Copyright 2020 Vircadia and contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="#0c0" d="M17,14H19V17H22V19H19V22H17V19H14V17H17V14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.53C20.94,12.58 19.54,12 18,12A6,6 0 0,0 12,18C12,19.09 12.29,20.12 12.8,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 552 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M16.5,12C19,12 21,14 21,16.5C21,17.38 20.75,18.21 20.31,18.9L23.39,22L22,23.39L18.88,20.32C18.19,20.75 17.37,21 16.5,21C14,21 12,19 12,16.5C12,14 14,12 16.5,12M16.5,14A2.5,2.5 0 0,0 14,16.5A2.5,2.5 0 0,0 16.5,19A2.5,2.5 0 0,0 19,16.5A2.5,2.5 0 0,0 16.5,14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.03C20.85,11.21 18.82,10 16.5,10A6.5,6.5 0 0,0 10,16.5C10,18.25 10.69,19.83 11.81,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 761 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="#0f0" d="M17,14H19V17H22V19H19V22H17V19H14V17H17V14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.53C20.94,12.58 19.54,12 18,12A6,6 0 0,0 12,18C12,19.09 12.29,20.12 12.8,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 552 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="white" d="M16.5,12C19,12 21,14 21,16.5C21,17.38 20.75,18.21 20.31,18.9L23.39,22L22,23.39L18.88,20.32C18.19,20.75 17.37,21 16.5,21C14,21 12,19 12,16.5C12,14 14,12 16.5,12M16.5,14A2.5,2.5 0 0,0 14,16.5A2.5,2.5 0 0,0 16.5,19A2.5,2.5 0 0,0 19,16.5A2.5,2.5 0 0,0 16.5,14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.03C20.85,11.21 18.82,10 16.5,10A6.5,6.5 0 0,0 10,16.5C10,18.25 10.69,19.83 11.81,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 775 B

View file

@ -0,0 +1,299 @@
//
// inventory.js
//
// Created by kasenvr@gmail.com on 2 Apr 2020
// Copyright 2020 Vircadia and contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/* global AvatarList Clipboard console Controller Entities location Messages MyAvatar Script ScriptDiscoveryService Settings
Tablet Vec3 Window */
(function () { // BEGIN LOCAL_SCOPE
"use strict";
var AppUi = Script.require('appUi');
var ui;
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
// VARIABLES
var inventoryDataSettingString = "inventoryApp.data";
var inventoryData;
var inventorySettingsString = "inventoryApp.settings";
var inventorySettings;
var RECEIVING_ITEM_QUEUE_LIMIT = 5;
var receivingItemQueue = [];
var NEARBY_USERS_SEARCH_RADIUS = 25;
// APP EVENT AND MESSAGING ROUTING
function onWebAppEventReceived(event) {
var eventJSON = JSON.parse(event);
if (eventJSON.app === "inventory") { // This is our web app!
// print("inventory.js received a web event: " + event);
if (eventJSON.command === "ready") {
initializeInventoryApp();
}
if (eventJSON.command === "web-to-script-inventory") {
receiveInventory(eventJSON.data);
}
if (eventJSON.command === "web-to-script-settings") {
receiveSettings(eventJSON.data);
}
if (eventJSON.command === "use-item") {
useItem(eventJSON.data);
}
if (eventJSON.command === "share-item") {
shareItem(eventJSON.data);
}
if (eventJSON.command === "web-to-script-request-nearby-users") {
sendNearbyUsers();
}
if (eventJSON.command === "web-to-script-request-receiving-item-queue") {
sendReceivingItemQueue();
}
if (eventJSON.command === "web-to-script-update-receiving-item-queue") {
updateReceivingItemQueue(eventJSON.data);
}
}
}
tablet.webEventReceived.connect(onWebAppEventReceived);
function sendToWeb(command, data) {
var dataToSend = {
"app": "inventory",
"command": command,
"data": data
};
tablet.emitScriptEvent(JSON.stringify(dataToSend));
}
var inventoryMessagesChannel = "com.vircadia.inventory";
function onMessageReceived(channel, message, sender, localOnly) {
if (channel === inventoryMessagesChannel) {
var messageJSON = JSON.parse(message);
// Window.alert("Passed 0 " + messageJSON.recipient + " vs " + MyAvatar.sessionUUID);
if (messageJSON.command === "share-item"
&& messageJSON.recipient === MyAvatar.sessionUUID) { // We are receiving an item.
// Window.alert("Passed 1 " + messageJSON.recipient + " vs " + MyAvatar.sessionUUID);
pushReceivedItemToQueue(sender, messageJSON.type, messageJSON.name, messageJSON.url);
}
}
// print("Message received:");
// print("- channel: " + channel);
// print("- message: " + message);
// print("- sender: " + sender);
// print("- localOnly: " + localOnly);
}
function sendMessage(dataToSend) {
Messages.sendMessage(inventoryMessagesChannel, JSON.stringify(dataToSend));
}
// END APP EVENT AND MESSAGING ROUTING
// SEND AND RECEIVE INVENTORY STATE
function receiveInventory(receivedInventoryData) {
inventoryData = receivedInventoryData;
saveInventory();
}
function sendInventory() {
sendToWeb("script-to-web-inventory", inventoryData);
}
// END SEND AND RECEIVE INVENTORY STATE
// SEND AND RECEIVE SETTINGS STATE
function receiveSettings(receivedSettingsData) {
inventorySettings = receivedSettingsData;
saveSettings();
}
function sendSettings() {
sendToWeb("script-to-web-settings", inventorySettings);
}
// END SEND AND RECEIVE SETTINGS STATE
function saveInventory() {
Settings.setValue(inventoryDataSettingString, inventoryData);
}
function loadInventory() {
inventoryData = Settings.getValue(inventoryDataSettingString);
}
function saveSettings() {
Settings.setValue(inventorySettingsString, inventorySettings);
}
function loadSettings() {
inventorySettings = Settings.getValue(inventorySettingsString);
}
function pushReceivedItemToQueue(senderUUID, type, name, url) {
console.info("Receiving an item:", name, "from:", senderUUID);
var getAvatarData = AvatarList.getAvatar(senderUUID);
var senderName = getAvatarData.sessionDisplayName;
var senderDistance = Vec3.distance(MyAvatar.position, getAvatarData.position);
var packageRequest = {
"senderUUID": senderUUID,
"senderName": senderName,
"senderDistance": senderDistance,
"data": {
"type": type,
"name": name,
"url": url
}
};
if (receivingItemQueue.length === RECEIVING_ITEM_QUEUE_LIMIT) {
receivingItemQueue = receivingItemQueue.slice(1, RECEIVING_ITEM_QUEUE_LIMIT);
}
receivingItemQueue.push(packageRequest);
ui.messagesWaiting(receivingItemQueue.length > 0);
}
function sendReceivingItemQueue() {
sendToWeb("script-to-web-receiving-item-queue", receivingItemQueue);
}
function updateReceivingItemQueue(data) {
receivingItemQueue = data;
ui.messagesWaiting(receivingItemQueue.length > 0);
}
function sendNearbyUsers() {
var nearbyUsers = AvatarList.getAvatarsInRange(MyAvatar.position, NEARBY_USERS_SEARCH_RADIUS);
var nearbyUsersToSend = [];
nearbyUsers.forEach(function(user) {
var objectToWrite;
var aviDetails = AvatarList.getAvatar(user);
var aviName = aviDetails.displayName;
var aviDistance = Vec3.distance(MyAvatar.position, aviDetails.position);
// Window.alert("aviName" + aviName + "user" + user + "MyAvatar.sessionUUID" + MyAvatar.sessionUUID);
if (user !== MyAvatar.sessionUUID
|| Controller.getValue(Controller.Hardware.Keyboard.Shift)) { // Don't add ourselves to the list!
objectToWrite = { "name": aviName, "distance": aviDistance, "uuid": user };
nearbyUsersToSend.push(objectToWrite);
}
});
sendToWeb("script-to-web-nearby-users", nearbyUsersToSend);
}
function useItem(item) {
//TODO: Add animation support for avatars...?
// Convert the item.type before checking it...
item.type = item.type.toUpperCase();
// Depending on the type, we decide how to load this item.
if (item.type === "SCRIPT") {
ScriptDiscoveryService.loadScript(item.url, true, false, false, true, false);
}
if (item.type === "MODEL") {
Entities.addEntity({
type: "Model",
position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1.5 })),
rotation: MyAvatar.orientation,
modelURL: item.url,
collisionless: true
});
}
if (item.type === "AVATAR") {
MyAvatar.useFullAvatarURL(item.url);
}
if (item.type === "PLACE") {
location.handleLookupString(item.url, true);
}
if (item.type === "JSON") {
var jsonToLoad = item.url;
if (jsonToLoad) {
if (Clipboard.importEntities(jsonToLoad)) {
Clipboard.pasteEntities(
Vec3.sum(
MyAvatar.position,
Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1.5 })
)
);
}
}
}
if (item.type === "UNKNOWN") {
// We don't know how to handle this yet.
Window.alert("Unknown item type, unable to use.");
}
}
function shareItem(data) {
data.command = "share-item";
sendMessage(data);
}
function initializeInventoryApp() {
sendSettings();
sendInventory();
sendReceivingItemQueue();
}
function onOpened() {
}
function onClosed() {
}
function startup() {
loadInventory();
loadSettings();
Messages.messageReceived.connect(onMessageReceived);
Messages.subscribe(inventoryMessagesChannel);
ui = new AppUi({
buttonName: "INVENTORY",
home: Script.resolvePath("index.html"),
graphicsDirectory: Script.resolvePath("./"), // Where your button icons are located
onOpened: onOpened,
onClosed: onClosed
});
}
startup();
Script.scriptEnding.connect(function () {
Messages.messageReceived.disconnect(onMessageReceived);
Messages.unsubscribe(inventoryMessagesChannel);
});
}()); // END LOCAL_SCOPE

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View file

@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 87.5 100"><defs><style>.cls-1{fill:#1697f6;}.cls-2{fill:#7bc6ff;}.cls-3{fill:#1867c0;}.cls-4{fill:#aeddff;}</style></defs><title>Artboard 46</title><polyline class="cls-1" points="43.75 0 23.31 0 43.75 48.32"/><polygon class="cls-2" points="43.75 62.5 43.75 100 0 14.58 22.92 14.58 43.75 62.5"/><polyline class="cls-3" points="43.75 0 64.19 0 43.75 48.32"/><polygon class="cls-4" points="64.58 14.58 87.5 14.58 43.75 100 43.75 62.5 64.58 14.58"/></svg>

After

Width:  |  Height:  |  Size: 539 B

View file

@ -0,0 +1,78 @@
/*
styles.css
Created by Kalila L. on 7 Apr 2020
Copyright 2020 Vircadia and contributors.
Distributed under the Apache License, Version 2.0.
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
*/
/* Top Level */
.draggable-card {
background-color: rgba(39, 39, 39, 1.0);
margin: 5px 0px;
}
.draggable-card .handle {
width: 40px !important;
}
.top-level-folder {
background-color: rgba(39, 39, 39, 1.0);
}
.top-level-folder .v-list-group__header__prepend-icon {
background-color: rgba(0, 0, 0, 0.3);
width: 50px;
height: 50px;
margin: 5px 5px 7px 0px !important;
padding: 5px 18px 5px 8px;
}
.top-level-folder .handle {
width: 40px !important;
}
.top-level-folder .folder-icon {
margin-right: 10px;
}
.top-level-folder .folder-button {
font-size: 0.795rem !important;
}
/* Second Level */
.v-list-group .column-item {
max-width: 100% !important;
margin-top: 5px;
margin-bottom: 5px;
}
.v-list-group .draggable-card {
background-color: rgba(0, 0, 0, 0.3);
padding-right: 16px;
padding-left: 0px !important;
}
.v-list-group .draggable-card .handle {
margin-right: 16px;
}
/* Menu Slideout */
.app-version {
text-align: center;
color: rgba(255, 255, 255, 0.6);
font-weight: lighter;
}
/* Universal */
.handle {
background-color: rgba(0, 0, 0, 0.3);
}
.inventoryApp::-webkit-scrollbar { width: 0 !important }

View file

@ -0,0 +1,391 @@
<!--
// ItemIterator.vue
//
// Created by Kalila L. on 13 April 2020.
// Copyright 2020 Vircadia and contributors..
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-->
<template>
<draggable :group="options" :list="itemsForIterator" handle=".handle">
<v-item-group
v-for="item in itemsForIterator"
v-bind:key="item.uuid"
>
<v-list-item
one-line
v-if="!item.items"
class="mx-auto draggable-card"
max-width="344"
outlined
>
<div class="handle pa-2">
<!-- <v-icon color="orange darken-2">mdi-blur-linear</v-icon> -->
<!-- <v-icon color="orange darken-2">mdi-package-variant</v-icon> -->
<v-icon color="orange darken-2">mdi-square-medium-outline</v-icon>
</div>
<v-list-item-content
class="pb-1 pt-2 pl-4"
>
<div v-show="settings.displayDensity.size > 0" class="overline" style="font-size: 0.825rem !important;">{{item.type}}</div>
<v-list-item-title class="subtitle-1 mb-1">{{item.name}}</v-list-item-title>
<v-list-item-subtitle v-show="settings.displayDensity.size == 2">{{item.url}}</v-list-item-subtitle>
</v-list-item-content>
<v-menu bottom left>
<template v-slot:activator="{ on }">
<!-- settings.displayDensity.size >= 1 -->
<v-btn
:style="{backgroundColor: (getIconColor(item.type)) }"
v-show="settings.displayDensity.size >= 1"
medium
fab
dark
v-on="on"
>
<v-icon>{{getIcon(item.type)}}</v-icon>
</v-btn>
<!-- settings.displayDensity.size < 1 -->
<v-btn
:style="{backgroundColor: (getIconColor(item.type)) }"
v-show="settings.displayDensity.size < 1"
small
fab
dark
v-on="on"
>
<v-icon>{{getIcon(item.type)}}</v-icon>
</v-btn>
</template>
<v-list color="grey darken-3">
<v-list-item
@click="sendEvent('use-item', { 'type': item.type, 'url': item.url })"
>
<v-list-item-title>Use</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-play</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="
editDialogStore.show = true;
editDialogStore.uuid = item.uuid;
editDialogStore.data.type = item.type.toUpperCase();
editDialogStore.data.folder = null;
editDialogStore.data.name = item.name;
editDialogStore.data.url = item.url;
"
>
<v-list-item-title>Edit</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-pencil</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="
shareDialogStore.show = true;
shareDialogStore.data.url = item.url;
shareDialogStore.data.uuid = item.uuid;
"
>
<v-list-item-title>Share</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-share</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="
removeDialogStore.show = true;
removeDialogStore.uuid = item.uuid;
"
color="red darken-1"
>
<v-list-item-title>Remove</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-minus</v-icon>
</v-list-item-action>
</v-list-item>
</v-list>
</v-menu>
</v-list-item>
<!-- The Folder List Item -->
<v-list-group
v-else
class="top-level-folder"
>
<!-- prepend-icon="mdi-blur-linear" put this in the list group, no idea how to make it a handle yet though... -->
<template v-slot:activator>
<v-list-item
one-line
class="mx-auto"
max-width="344"
outlined
>
<v-icon class="folder-icon" color="teal">mdi-folder-settings</v-icon>
{{item.name}}
</v-list-item>
</template>
<div class="text-center my-2">
<v-btn medium tile color="purple" class="mx-1 folder-button"
@click="
editFolderDialogStore.data.uuid = item.uuid;
editFolderDialogStore.data.name = item.name;
editFolderDialogStore.show = true;
"
>
<v-icon>mdi-pencil</v-icon>
</v-btn>
<v-btn medium tile color="red" class="mx-1 folder-button"
@click="
removeFolderDialogStore.show = true;
removeFolderDialogStore.uuid = item.uuid;
"
>
<v-icon>mdi-minus</v-icon>
</v-btn>
<v-menu bottom left>
<template v-slot:activator="{ on }">
<v-btn
medium tile
color="blue"
class="mx-1 folder-button"
v-on="on"
>
<v-icon>mdi-sort</v-icon>
</v-btn>
</template>
<v-list color="grey darken-3">
<v-list-item
@click="sortFolder(item.uuid, 'az');"
>
<v-list-item-title>A-Z</v-list-item-title>
<v-list-item-action>
<v-icon large>mdi-sort-alphabetical-ascending</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="sortFolder(item.uuid, 'za');"
>
<v-list-item-title>Z-A</v-list-item-title>
<v-list-item-action>
<v-icon large>mdi-sort-alphabetical-descending</v-icon>
</v-list-item-action>
</v-list-item>
</v-list>
</v-menu>
</div>
<v-container fluid>
<itemiterator v-bind:key="item.uuid" :itemsForIterator="item.items"></itemiterator>
</v-container>
</v-list-group>
</v-item-group>
</draggable>
</template>
<script>
import { EventBus } from '../plugins/event-bus.js';
import draggable from 'vuedraggable';
export default {
name: 'itemiterator',
components: {
draggable
},
props: ['itemsForIterator'],
data: () => ({
settings: {}
}),
created: function () {
this.settings = this.$store.state.settings;
},
computed: {
options : function (){
return {
name: 'column-item',
pull: true,
put: true
}
},
settingsChanged() {
return this.$store.state.settings;
},
addDialogStore: {
get() {
return this.$store.state.addDialog;
},
set(value) {
this.$store.commit('mutate', {
property: 'addDialog',
with: value
});
}
},
editDialogStore: {
get() {
return this.$store.state.editDialog;
},
set(value) {
this.$store.commit('mutate', {
property: 'editDialog',
with: value
});
}
},
editFolderDialogStore: {
get() {
return this.$store.state.editFolderDialog;
},
set(value) {
this.$store.commit('mutate', {
property: 'editFolderDialog',
with: value
});
}
},
shareDialogStore: {
get() {
return this.$store.state.shareDialog;
},
set(value) {
this.$store.commit('mutate', {
property: 'shareDialog',
with: value
});
}
},
removeFolderDialogStore: {
get() {
return this.$store.state.removeFolderDialog;
},
set(value) {
this.$store.commit('mutate', {
property: 'removeFolderDialog',
with: value
});
}
},
removeDialogStore: {
get() {
return this.$store.state.removeDialog;
},
set(value) {
this.$store.commit('mutate', {
property: 'removeDialog',
with: value
});
}
}
},
watch: {
settingsChanged (newVal, oldVal) {
console.info ("Settings previous value:", oldVal);
if (newVal) {
this.settings = newVal;
}
}
},
methods: {
sendEvent: function(command, data) {
EventBus.$emit(command, data);
},
getIcon: function(itemType) {
itemType = itemType.toUpperCase();
var returnedItemIcon;
if (this.$store.state.iconType[itemType]) {
returnedItemIcon = this.$store.state.iconType[itemType].icon;
} else {
returnedItemIcon = this.$store.state.iconType.UNKNOWN.icon;
}
return returnedItemIcon;
},
getIconColor: function(itemType) {
itemType = itemType.toUpperCase();
var returnedItemIconColor;
if (this.$store.state.iconType[itemType]) {
returnedItemIconColor = this.$store.state.iconType[itemType].color;
} else {
returnedItemIconColor = this.$store.state.iconType.UNKNOWN.color;
}
return returnedItemIconColor;
},
sortFolder: function(uuid, sort) {
var findFolder = this.searchForItem(uuid);
if (findFolder) {
if (sort === "az") {
findFolder.returnedItem.items.sort(function(a, b) {
var nameA = a.name.toUpperCase(); // ignore upper and lowercase
var nameB = b.name.toUpperCase(); // ignore upper and lowercase
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
}
if (sort === "za") {
findFolder.returnedItem.items.sort(function(a, b) {
var nameA = a.name.toUpperCase(); // ignore upper and lowercase
var nameB = b.name.toUpperCase(); // ignore upper and lowercase
if (nameA > nameB) {
return -1;
}
if (nameA < nameB) {
return 1;
}
// names must be equal
return 0;
});
}
}
},
searchForItem: function(uuid) {
var foundItem = this.recursiveSingularSearch(uuid, this.itemsForIterator);
if (foundItem) {
return {
"returnedItem": foundItem.returnedItem,
"iteration": foundItem.iteration,
"parentArray": foundItem.parentArray,
"itemUUID": uuid,
}
}
},
recursiveSingularSearch: function(uuid, indexToSearch) {
for (var i = 0; i < indexToSearch.length; i++) {
if (indexToSearch[i].uuid == uuid) {
var foundItem = {
"returnedItem": indexToSearch[i],
"iteration": i,
"parentArray": indexToSearch,
}
return foundItem;
} else if (Object.prototype.hasOwnProperty.call(indexToSearch[i], "items") && indexToSearch[i].items.length > 0) {
return this.recursiveSingularSearch(uuid, indexToSearch[i].items);
}
}
},
}
};
</script>

View file

@ -0,0 +1,272 @@
<!--
NotUsing.vue
Created by Kalila L. on 7 Apr 2020
Copyright 2020 Vircadia and contributors.
Distributed under the Apache License, Version 2.0.
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-->
<template v-if="!disabledProp">
<v-data-iterator
:items="items"
hide-default-footer
>
<template>
<v-col
cols="12"
sm="6"
md="4"
lg="3"
class="py-1 column-item"
>
<draggable :group="options" :list="items" handle=".handle">
<v-item-group
v-for="item in items"
v-bind:key="item.uuid"
>
<v-list-item
one-line
v-if="!item.hasChildren"
class="mx-auto draggable-card"
max-width="344"
outlined
>
<div class="handle pa-2">
<v-icon color="orange darken-2">mdi-blur-linear</v-icon>
</div>
<v-list-item-content
class="pb-1 pt-2 pl-4"
>
<div v-show="settings.displayDensity.size > 0" class="overline" style="font-size: 0.825rem !important;">{{item.type}}</div>
<v-list-item-title class="subtitle-1 mb-1">{{item.name}}</v-list-item-title>
<v-list-item-subtitle v-show="settings.displayDensity.size == 2">{{item.url}}</v-list-item-subtitle>
</v-list-item-content>
<v-menu bottom left>
<template v-slot:activator="{ on }">
<!-- settings.displayDensity.size >= 1 -->
<v-btn
:style="{backgroundColor: (getIconColor(item.type)) }"
v-show="settings.displayDensity.size >= 1"
medium
fab
dark
v-on="on"
>
<v-icon>{{getIcon(item.type)}}</v-icon>
</v-btn>
<!-- settings.displayDensity.size < 1 -->
<v-btn
:style="{backgroundColor: (getIconColor(item.type)) }"
v-show="settings.displayDensity.size < 1"
small
fab
dark
v-on="on"
>
<v-icon>{{getIcon(item.type)}}</v-icon>
</v-btn>
</template>
<v-list color="grey darken-3">
<v-list-item
@click="useItem(item.type, item.url)"
>
<v-list-item-title>Use</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-play</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="
editDialog.show = true;
editDialog.uuid = item.uuid;
editDialog.data.type = item.type.toUpperCase();
editDialog.data.folder = null;
editDialog.data.name = item.name;
editDialog.data.url = item.url;
getFolderList('edit');
"
>
<v-list-item-title>Edit</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-pencil</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="shareDialog.show = true; shareDialog.data.url = item.url; shareDialog.data.uuid = item.uuid; sendAppMessage('web-to-script-request-nearby-users', '')"
>
<v-list-item-title>Share</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-share</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="removeDialog.show = true; removeDialog.uuid = item.uuid;"
color="red darken-1"
>
<v-list-item-title>Remove</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-minus</v-icon>
</v-list-item-action>
</v-list-item>
</v-list>
</v-menu>
</v-list-item>
<!-- The Folder List Item -->
<v-list-group
v-if="item.hasChildren"
class="top-level-folder"
>
<!-- prepend-icon="mdi-blur-linear" put this in the list group, no idea how to make it a handle yet though... -->
<template v-slot:activator>
<v-list-item
one-line
class="mx-auto"
max-width="344"
outlined
>
<v-icon class="folder-icon" color="teal">mdi-folder-settings</v-icon>
{{item.name}}
</v-list-item>
</template>
<div class="text-center my-2">
<v-btn medium tile color="purple" class="mx-1 folder-button"
@click="
editFolderDialog.show = true;
editFolderDialog.uuid = item.uuid;
editFolderDialog.data.name = item.name;
"
>
<v-icon>mdi-pencil</v-icon>
</v-btn>
<v-btn medium tile color="red" class="mx-1 folder-button"
@click="removeFolderDialog.show = true; removeFolderDialog.uuid = item.uuid;"
>
<v-icon>mdi-minus</v-icon>
</v-btn>
<v-btn medium tile color="blue" class="mx-1 folder-button"
@click="sortFolder(item.uuid);"
>
<v-icon>mdi-ab-testing</v-icon>
</v-btn>
</div>
<v-col
cols="12"
sm="6"
md="4"
lg="3"
class="py-1 column-item"
>
<draggable
:list="item.items"
:group="options"
>
<v-item-group
v-for="item in item.items"
v-bind:key="item.uuid"
>
<v-list-item
one-line
class="mx-auto draggable-card"
outlined
>
<div class="handle pa-2">
<v-icon color="orange darken-2">mdi-blur-linear</v-icon>
</div>
<v-list-item-content class="pb-1 pt-2">
<div v-show="settings.displayDensity.size > 0" class="overline" style="font-size: 0.825rem !important;">{{item.type}}</div>
<v-list-item-title class="subtitle-1 mb-1">{{item.name}}</v-list-item-title>
<v-list-item-subtitle v-show="settings.displayDensity.size == 2">{{item.url}}</v-list-item-subtitle>
</v-list-item-content>
<v-menu bottom left>
<template v-slot:activator="{ on }">
<!-- settings.displayDensity.size >= 1 -->
<v-btn
:style="{backgroundColor: (getIconColor(item.type)) }"
v-show="settings.displayDensity.size >= 1"
medium
fab
dark
v-on="on"
>
<v-icon>{{getIcon(item.type)}}</v-icon>
</v-btn>
<!-- settings.displayDensity.size < 1 -->
<v-btn
:style="{backgroundColor: (getIconColor(item.type)) }"
v-show="settings.displayDensity.size < 1"
small
fab
dark
v-on="on"
>
<v-icon>{{getIcon(item.type)}}</v-icon>
</v-btn>
</template>
<v-list color="grey darken-3">
<v-list-item
@click="useItem(item.type, item.url)"
>
<v-list-item-title>Use</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-play</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="
editDialog.show = true;
editDialog.uuid = item.uuid;
editDialog.data.type = item.type.toUpperCase();
editDialog.data.folder = null;
editDialog.data.name = item.name;
editDialog.data.url = item.url;
getFolderList('edit');
"
>
<v-list-item-title>Edit</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-pencil</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="shareDialog.show = true; shareDialog.data.url = item.url; shareDialog.data.uuid = item.uuid; sendAppMessage('web-to-script-request-nearby-users', '')"
>
<v-list-item-title>Share</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-share</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="removeDialog.show = true; removeDialog.uuid = item.uuid;"
color="red darken-1"
>
<v-list-item-title>Remove</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-minus</v-icon>
</v-list-item-action>
</v-list-item>
</v-list>
</v-menu>
</v-list-item>
</v-item-group>
</draggable>
</v-col>
</v-list-group>
</v-item-group>
</draggable>
</v-col>
</template>
</v-data-iterator>
</template>

View file

@ -0,0 +1,22 @@
/*
main.js
Created by Kalila L. on 7 Apr 2020
Copyright 2020 Vircadia and contributors.
Distributed under the Apache License, Version 2.0.
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
*/
import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify';
import { store } from './plugins/store';
Vue.config.productionTip = false;
window.vm = new Vue({
vuetify,
store,
render: h => h(App)
}).$mount('#app');

View file

@ -0,0 +1,12 @@
/*
event-bus.js
Created by Kalila L. on 21 May 2020.
Copyright 2020 Vircadia and contributors.
Distributed under the Apache License, Version 2.0.
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
*/
import Vue from 'vue';
export const EventBus = new Vue();

View file

@ -0,0 +1,321 @@
/*
store.js
Created by Kalila L. on 16 Apr 2020.
Copyright 2020 Vircadia and contributors.
Distributed under the Apache License, Version 2.0.
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
*/
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.Store({
devtools: true,
state: {
items: [
// This is test data and is primarily used for in browser development.
{
"type": "script",
"name": "VRGrabScale",
"url": "https://gooawefaweawfgle.com/vr.js",
"folder": "No Folder",
"uuid": "54254354353"
},
{
"name": "Test Folder",
"folder": "No Folder",
"items": [
{
"name": "inception1",
"folder": "Test Folder",
"items": [
{
"name": "inception2",
"folder": "Test Folder",
"items": [
{
"type": "script",
"name": "itemincepted",
"url": "https://googfdafsgaergale.com/vr.js",
"folder": "FolderWithinAFolder",
"uuid": "hkjkjhkjk",
},
],
"uuid": "adsfa32"
},
],
"uuid": "s4g4sg"
},
],
"uuid": "sdfsdf",
},
{
"type": "script",
"name": "VRGrabScale",
"url": "https://googfdafsgaergale.com/vr.js",
"folder": "No Folder",
"uuid": "54hgfhgf254354353",
},
{
"type": "script",
"name": "TEST",
"url": "https://gooadfdagle.com/vr.js",
"folder": "No Folder",
"uuid": "542rfwat4t5fsddf4354353",
},
{
"type": "json",
"name": "TESTJSON",
"url": "https://gooadfdagle.com/vr.json",
"folder": "No Folder",
"uuid": "542rfwat4t54354353",
},
{
"type": "script",
"name": "TESTLONGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG",
"url": "https://googfdaffle.com/vrLONGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG.js",
"folder": "No Folder",
"uuid": "5425ggsrg45354353",
},
{
"type": "whatttype",
"name": "BrokenIcon",
"url": "https://googfdaffle.com/vrLONGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG.js",
"folder": "No Folder",
"uuid": "5425ggsrg4fdaffdff535asdasd4353",
},
{
"type": "avatar",
"name": "AVI",
"url": "https://googlfadfe.com/vr.fst",
"folder": "No Folder",
"uuid": "542gregg45s3g4354353",
},
{
"type": "avatar",
"name": "AVI",
"url": "https://googlefdaf.com/vr.fst",
"folder": "No Folder",
"uuid": "5420798-087-54354353",
},
{
"type": "model",
"name": "3D MODEL",
"url": "https://googlee.com/vr.fbx",
"folder": "No Folder",
"uuid": "54254354980-7667jt353",
},
{
"type": "place",
"name": "PLACE DOMAIN",
"url": "https://googleee.com/vr.fbx",
"folder": "No Folder",
"uuid": "542543sg45s4gg54353",
},
],
settings: {
"displayDensity": {
"size": 1,
"labels": [
"List",
"Compact",
"Large",
],
},
},
iconType: {
"SCRIPT": {
"icon": "mdi-code-tags",
"color": "red",
},
"MODEL": {
"icon": "mdi-video-3d",
"color": "green",
},
"AVATAR": {
"icon": "mdi-account-convert",
"color": "purple",
},
"PLACE": {
"icon": "mdi-earth",
"color": "#0097A7", // cyan darken-2
},
"JSON": {
"icon": "mdi-inbox-multiple",
"color": "#37474F", // blue-grey darken-3
},
"UNKNOWN": {
"icon": "mdi-help",
"color": "grey",
}
},
supportedItemTypes: [
"SCRIPT",
"MODEL",
"AVATAR",
"PLACE",
"JSON",
"UNKNOWN",
],
removeDialog: {
show: false,
uuid: null,
},
removeFolderDialog: {
show: false,
uuid: null,
},
createFolderDialog: {
show: false,
valid: false,
data: {
"name": null,
},
},
addDialog: {
show: false,
valid: false,
data: {
"name": null,
"folder": null,
"url": null,
},
},
editDialog: {
show: false,
valid: false,
uuid: null, //
data: {
"type": null,
"name": null,
"url": null,
"folder": null,
},
},
editFolderDialog: {
show: false,
valid: false,
uuid: null, //
data: {
"name": null,
"folder": null,
},
},
receiveDialog: {
show: false,
valid: false,
data: {
"userUUID": null,
"userDisplayName": null,
"name": null,
"folder": null,
"type": null,
"url": null,
},
},
shareDialog: {
show: false,
valid: false,
data: {
"uuid": null, // UUID of the item you want to share. THIS IS THE KEY.
"url": null, // The item you want to share.
"recipient": null,
}
},
},
mutations: {
mutate (state, payload) {
state[payload.property] = payload.with;
// console.info("Payload:", payload.property, "with:", payload.with, "state is now:", this.state);
},
sortTopInventory (state, payload) {
let { items } = state;
if (payload.sort === "az") {
state.items.sort(function(a, b) {
var nameA = a.name.toUpperCase(); // ignore upper and lowercase
var nameB = b.name.toUpperCase(); // ignore upper and lowercase
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
}
if (payload.sort === "za") {
state.items.sort(function(a, b) {
var nameA = a.name.toUpperCase(); // ignore upper and lowercase
var nameB = b.name.toUpperCase(); // ignore upper and lowercase
if (nameA > nameB) {
return -1;
}
if (nameA < nameB) {
return 1;
}
// names must be equal
return 0;
});
}
Vue.set(state,'items', items);
},
pushToItems (state, payload) {
let { items } = state;
items.push(payload);
Vue.set(state,'items', items);
},
moveFolder (state, payload) {
let { items } = state;
if (payload.parentFolderUUID === "top") {
payload.findFolder.returnedItem.folder = "No Folder";
// console.info("Going to push...", payload.findFolder.returnedItem);
// console.info("Containing these items...", payload.findFolder.returnedItem.items);
items.push(payload.findFolder.returnedItem);
Vue.set(state, 'items', items);
} else if (payload.findParentFolder) {
// console.info("Going to push...", payload.findFolder.returnedItem);
// console.info("Containing these items...", payload.findFolder.returnedItem.items);
// console.info("Into...", payload.findParentFolder.returnedItem);
payload.findFolder.returnedItem.folder = payload.findParentFolder.name;
payload.findParentFolder.returnedItem.items.push(payload.findFolder.returnedItem);
Vue.set(state,'items', items);
}
},
moveItem (state, payload) {
let { items } = state;
if (payload.parentFolderUUID === "top") {
payload.findItem.returnedItem.folder = "No Folder";
// console.info("Going to push...", payload.findFolder.returnedItem);
// console.info("Containing these items...", payload.findFolder.returnedItem.items);
items.push(payload.findItem.returnedItem);
Vue.set(state,'items', items);
} else if (payload.findParentFolder) {
// console.info("Going to push...", payload.findFolder.returnedItem);
// console.info("Containing these items...", payload.findFolder.returnedItem.items);
// console.info("Into...", payload.findParentFolder.returnedItem);
payload.findItem.returnedItem.folder = payload.findParentFolder.name;
payload.findParentFolder.returnedItem.items.push(payload.findItem.returnedItem);
Vue.set(state,'items', items);
}
}
}
})

View file

@ -0,0 +1,17 @@
/*
vuetify.js
Created by Kalila L. on 7 Apr 2020
Copyright 2020 Vircadia and contributors.
Distributed under the Apache License, Version 2.0.
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
*/
import Vue from 'vue';
import Vuetify from 'vuetify/lib';
Vue.use(Vuetify);
export default new Vuetify({
});

View file

@ -0,0 +1,17 @@
/*
vue.config.js
Created by Kalila L. on 7 Apr 2020
Copyright 2020 Vircadia and contributors.
Distributed under the Apache License, Version 2.0.
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
*/
module.exports = {
publicPath: "./",
assetsDir: "./",
"transpileDependencies": [
"vuetify"
]
}