mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-19 14:53:50 +02:00
World Favorites Import/Export
This commit is contained in:
183
html/src/app.js
183
html/src/app.js
@@ -15073,6 +15073,14 @@ speechSynthesis.getVoices();
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$app.methods.addFavoriteWorld = function (ref, group) {
|
||||||
|
return API.addFavorite({
|
||||||
|
type: 'world',
|
||||||
|
favoriteId: ref.id,
|
||||||
|
tags: group.name
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
$app.methods.addFavoriteAvatar = function (ref, group) {
|
$app.methods.addFavoriteAvatar = function (ref, group) {
|
||||||
API.addFavorite({
|
API.addFavorite({
|
||||||
type: 'avatar',
|
type: 'avatar',
|
||||||
@@ -19988,6 +19996,181 @@ speechSynthesis.getVoices();
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// App: world favorite import
|
||||||
|
|
||||||
|
$app.data.worldImportDialog = {
|
||||||
|
visible: false,
|
||||||
|
loading: false,
|
||||||
|
progress: 0,
|
||||||
|
progressTotal: 0,
|
||||||
|
input: '',
|
||||||
|
worldIdList: new Set(),
|
||||||
|
errors: '',
|
||||||
|
worldImportFavoriteGroup: null,
|
||||||
|
importProgress: 0,
|
||||||
|
importProgressTotal: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
$app.data.worldImportTable = {
|
||||||
|
data: [],
|
||||||
|
tableProps: {
|
||||||
|
stripe: true,
|
||||||
|
size: 'mini'
|
||||||
|
},
|
||||||
|
layout: 'table'
|
||||||
|
};
|
||||||
|
|
||||||
|
$app.methods.showWorldImportDialog = function () {
|
||||||
|
this.$nextTick(() => adjustDialogZ(this.$refs.avatarDialog.$el));
|
||||||
|
var D = this.worldImportDialog;
|
||||||
|
this.resetWorldImport();
|
||||||
|
D.visible = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
$app.methods.processWorldImportList = async function () {
|
||||||
|
var D = this.worldImportDialog;
|
||||||
|
D.loading = true;
|
||||||
|
var regexWorldId =
|
||||||
|
/wrld_[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}/g;
|
||||||
|
var match = [];
|
||||||
|
var worldIdList = new Set();
|
||||||
|
while ((match = regexWorldId.exec(D.input)) !== null) {
|
||||||
|
worldIdList.add(match[0]);
|
||||||
|
}
|
||||||
|
D.input = '';
|
||||||
|
D.errors = '';
|
||||||
|
D.progress = 0;
|
||||||
|
D.progressTotal = worldIdList.size;
|
||||||
|
var data = Array.from(worldIdList);
|
||||||
|
for (var i = 0; i < data.length; ++i) {
|
||||||
|
var worldId = data[i];
|
||||||
|
if (!D.visible) {
|
||||||
|
this.resetWorldImport();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!D.worldIdList.has(worldId)) {
|
||||||
|
try {
|
||||||
|
var args = await API.getWorld({
|
||||||
|
worldId
|
||||||
|
});
|
||||||
|
this.worldImportTable.data.push(args.ref);
|
||||||
|
D.worldIdList.add(worldId);
|
||||||
|
} catch (err) {
|
||||||
|
D.errors = D.errors.concat(
|
||||||
|
`WorldId: ${worldId}\n${err}\n\n`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
D.progress++;
|
||||||
|
if (D.progress === worldIdList.size) {
|
||||||
|
D.progress = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
D.loading = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
$app.methods.deleteItemWorldImport = function (ref) {
|
||||||
|
var D = this.worldImportDialog;
|
||||||
|
removeFromArray(this.worldImportTable.data, ref);
|
||||||
|
D.worldIdList.delete(ref.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
$app.methods.resetWorldImport = function () {
|
||||||
|
var D = this.worldImportDialog;
|
||||||
|
D.input = '';
|
||||||
|
D.errors = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
$app.methods.clearWorldImportTable = function () {
|
||||||
|
var D = this.worldImportDialog;
|
||||||
|
this.worldImportTable.data = [];
|
||||||
|
D.worldIdList = new Set();
|
||||||
|
};
|
||||||
|
|
||||||
|
$app.methods.selectWorldImportGroup = function (group) {
|
||||||
|
var D = this.worldImportDialog;
|
||||||
|
D.worldImportFavoriteGroup = group;
|
||||||
|
};
|
||||||
|
|
||||||
|
$app.methods.importWorldImportTable = async function () {
|
||||||
|
var D = this.worldImportDialog;
|
||||||
|
D.loading = true;
|
||||||
|
if (!D.worldImportFavoriteGroup) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = [...this.worldImportTable.data].reverse();
|
||||||
|
D.importProgressTotal = data.length;
|
||||||
|
try {
|
||||||
|
for (var i = data.length - 1; i >= 0; i--) {
|
||||||
|
var ref = data[i];
|
||||||
|
await this.addFavoriteWorld(ref, D.worldImportFavoriteGroup);
|
||||||
|
removeFromArray(this.worldImportTable.data, ref);
|
||||||
|
D.worldIdList.delete(ref.id);
|
||||||
|
D.importProgress++;
|
||||||
|
if (D.importProgress === data.length) {
|
||||||
|
D.importProgress = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
D.errors = `Name: ${ref.name}\nWorldId: ${ref.id}\n${err}\n\n`;
|
||||||
|
} finally {
|
||||||
|
D.importProgress = 0;
|
||||||
|
D.importProgressTotal = 0;
|
||||||
|
D.loading = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
API.$on('LOGIN', function () {
|
||||||
|
$app.clearWorldImportTable();
|
||||||
|
$app.resetWorldImport();
|
||||||
|
$app.worldImportDialog.visible = false;
|
||||||
|
$app.worldImportFavoriteGroup = null;
|
||||||
|
|
||||||
|
$app.worldExportDialogVisible = false;
|
||||||
|
$app.worldExportFavoriteGroup = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
// App: world favorite export
|
||||||
|
|
||||||
|
$app.data.worldExportDialogVisible = false;
|
||||||
|
$app.data.worldExportContent = '';
|
||||||
|
$app.data.worldExportFavoriteGroup = null;
|
||||||
|
|
||||||
|
$app.methods.showWorldExportDialog = function () {
|
||||||
|
this.worldExportFavoriteGroup = null;
|
||||||
|
this.updateWorldExportDialog();
|
||||||
|
this.worldExportDialogVisible = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
$app.methods.updateWorldExportDialog = function () {
|
||||||
|
var _ = function (str) {
|
||||||
|
if (/[\x00-\x1f,"]/.test(str) === true) {
|
||||||
|
return `"${str.replace(/"/g, '""')}"`;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
var lines = ['WorldID,Name'];
|
||||||
|
API.favoriteWorldGroups.forEach((group) => {
|
||||||
|
if (
|
||||||
|
!this.worldExportFavoriteGroup ||
|
||||||
|
this.worldExportFavoriteGroup === group
|
||||||
|
) {
|
||||||
|
$app.favoriteWorlds.forEach((ref) => {
|
||||||
|
if (group.key === ref.groupKey) {
|
||||||
|
lines.push(`${_(ref.id)},${_(ref.name)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.worldExportContent = lines.join('\n');
|
||||||
|
};
|
||||||
|
|
||||||
|
$app.methods.selectWorldExportGroup = function (group) {
|
||||||
|
this.worldExportFavoriteGroup = group;
|
||||||
|
this.updateWorldExportDialog();
|
||||||
|
};
|
||||||
|
|
||||||
$app = new Vue($app);
|
$app = new Vue($app);
|
||||||
window.$app = $app;
|
window.$app = $app;
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -537,6 +537,8 @@ html
|
|||||||
el-button(type="text" icon="el-icon-close" size="mini" @click.stop="deleteFavorite(favorite.id)" style="margin-left:5px")
|
el-button(type="text" icon="el-icon-close" size="mini" @click.stop="deleteFavorite(favorite.id)" style="margin-left:5px")
|
||||||
el-tab-pane(label="Worlds")
|
el-tab-pane(label="Worlds")
|
||||||
el-collapse(style="border:0")
|
el-collapse(style="border:0")
|
||||||
|
el-button(size="small" @click="showWorldExportDialog") Export
|
||||||
|
el-button(size="small" @click="showWorldImportDialog") Import
|
||||||
el-collapse-item(v-for="group in API.favoriteWorldGroups" :key="group.name")
|
el-collapse-item(v-for="group in API.favoriteWorldGroups" :key="group.name")
|
||||||
template(slot="title")
|
template(slot="title")
|
||||||
span(v-text="group.displayName" style="font-weight:bold;font-size:14px;margin-left:10px")
|
span(v-text="group.displayName" style="font-weight:bold;font-size:14px;margin-left:10px")
|
||||||
@@ -2962,6 +2964,66 @@ html
|
|||||||
template(v-once #default="scope")
|
template(v-once #default="scope")
|
||||||
span(v-text="scope.row.count")
|
span(v-text="scope.row.count")
|
||||||
|
|
||||||
|
|
||||||
|
//- dialog: export world list
|
||||||
|
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" :visible.sync="worldExportDialogVisible" title="World Favorites Export" width="650px")
|
||||||
|
el-dropdown(@click.native.stop trigger="click" size="small")
|
||||||
|
el-button(size="mini")
|
||||||
|
span(v-if="worldExportFavoriteGroup") {{ worldExportFavoriteGroup.displayName }} ({{ worldExportFavoriteGroup.count }}/{{ worldExportFavoriteGroup.capacity }}) #[i.el-icon-arrow-down.el-icon--right]
|
||||||
|
span(v-else) All Favorites #[i.el-icon-arrow-down.el-icon--right]
|
||||||
|
el-dropdown-menu(#default="dropdown")
|
||||||
|
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectWorldExportGroup(null)") All Favorites
|
||||||
|
template(v-for="groupAPI in API.favoriteWorldGroups" :key="groupAPI.name")
|
||||||
|
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectWorldExportGroup(groupAPI)" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
|
||||||
|
br
|
||||||
|
el-input(type="textarea" v-if="worldExportDialogVisible" v-model="worldExportContent" size="mini" rows="15" resize="none" readonly style="margin-top:15px" @click.native="$event.target.tagName === 'TEXTAREA' && $event.target.select()")
|
||||||
|
|
||||||
|
//- dialog: World import dialog
|
||||||
|
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" :visible.sync="worldImportDialog.visible" title="World Favorites Import" width="650px")
|
||||||
|
div(style="font-size:12px")
|
||||||
|
| Enter a list of world IDs
|
||||||
|
el-input(type="textarea" v-model="worldImportDialog.input" size="mini" rows="10" resize="none" style="margin-top:15px")
|
||||||
|
el-button(size="small" @click="processWorldImportList" :disabled="!worldImportDialog.input") Process List
|
||||||
|
span(v-if="worldImportDialog.progress" style="margin-top:10px") Progress: {{ worldImportDialog.progress }}/{{ worldImportDialog.progressTotal }}
|
||||||
|
br
|
||||||
|
el-dropdown(@click.native.stop trigger="click" size="small")
|
||||||
|
el-button(size="mini")
|
||||||
|
span(v-if="worldImportDialog.worldImportFavoriteGroup") {{ worldImportDialog.worldImportFavoriteGroup.displayName }} ({{ worldImportDialog.worldImportFavoriteGroup.count }}/{{ worldImportDialog.worldImportFavoriteGroup.capacity }}) #[i.el-icon-arrow-down.el-icon--right]
|
||||||
|
span(v-else) Select Group #[i.el-icon-arrow-down.el-icon--right]
|
||||||
|
el-dropdown-menu(#default="dropdown")
|
||||||
|
template(v-for="groupAPI in API.favoriteWorldGroups" :key="groupAPI.name")
|
||||||
|
el-dropdown-item(style="display:block;margin:10px 0" @click.native="selectWorldImportGroup(groupAPI)" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }}/{{ groupAPI.capacity }})
|
||||||
|
el-button(size="small" @click="importWorldImportTable" style="margin:10px" :disabled="worldImportTable.data.length === 0 || !worldImportDialog.worldImportFavoriteGroup") Import Worlds
|
||||||
|
span(v-if="worldImportDialog.worldImportFavoriteGroup") {{ worldImportTable.data.length }} / {{ worldImportDialog.worldImportFavoriteGroup.capacity - worldImportDialog.worldImportFavoriteGroup.count }}
|
||||||
|
span(v-if="worldImportDialog.importProgress" style="margin:10px") Import Progress: {{ worldImportDialog.importProgress }}/{{ worldImportDialog.importProgressTotal }}
|
||||||
|
br
|
||||||
|
el-button(size="small" @click="clearWorldImportTable") Clear Table
|
||||||
|
br
|
||||||
|
template(v-if="worldImportDialog.errors")
|
||||||
|
el-button(size="small" @click="worldImportDialog.errors = ''") Clear Errors
|
||||||
|
h2(style="font-weight:bold;margin:0") Errors:
|
||||||
|
pre(v-text="worldImportDialog.errors" style="white-space:pre-wrap;font-size:12px")
|
||||||
|
data-tables(v-if="worldImportDialog.visible" v-bind="worldImportTable" v-loading="worldImportDialog.loading" style="margin-top:10px")
|
||||||
|
el-table-column(label="Image" width="70" prop="thumbnailImageUrl")
|
||||||
|
template(v-once #default="scope")
|
||||||
|
el-popover(placement="right" height="500px" trigger="hover")
|
||||||
|
img.friends-list-avatar(slot="reference" v-lazy="scope.row.thumbnailImageUrl")
|
||||||
|
img.friends-list-avatar(v-lazy="scope.row.imageUrl" style="height:500px;cursor:pointer" @click="openExternalLink(scope.row.imageUrl)")
|
||||||
|
el-table-column(label="Name" prop="name")
|
||||||
|
template(v-once #default="scope")
|
||||||
|
span.x-link(v-text="scope.row.name" @click="showWorldDialog(scope.row.id)")
|
||||||
|
el-table-column(label="Author" width="120" prop="authorName")
|
||||||
|
template(v-once #default="scope")
|
||||||
|
span.x-link(v-text="scope.row.authorName" @click="showUserDialog(scope.row.authorId)")
|
||||||
|
el-table-column(label="Status" width="70" prop="releaseStatus")
|
||||||
|
template(v-once #default="scope")
|
||||||
|
span(v-text="scope.row.releaseStatus" v-if="scope.row.releaseStatus === 'public'" style="color:#67c23a")
|
||||||
|
span(v-text="scope.row.releaseStatus" v-else-if="scope.row.releaseStatus === 'private'" style="color:#f56c6c")
|
||||||
|
span(v-text="scope.row.releaseStatus" v-else)
|
||||||
|
el-table-column(label="Action" width="90" align="right")
|
||||||
|
template(v-once #default="scope")
|
||||||
|
el-button(type="text" icon="el-icon-close" size="mini" @click="deleteItemWorldImport(scope.row)")
|
||||||
|
|
||||||
//- dialog: open source software notice
|
//- dialog: open source software notice
|
||||||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" :visible.sync="ossDialog" title="Open Source Software Notice" width="650px")
|
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" :visible.sync="ossDialog" title="Open Source Software Notice" width="650px")
|
||||||
div(v-if="ossDialog" style="height:350px;overflow:hidden scroll;word-break:break-all")
|
div(v-if="ossDialog" style="height:350px;overflow:hidden scroll;word-break:break-all")
|
||||||
|
|||||||
Reference in New Issue
Block a user