Groups sorting

This commit is contained in:
Natsumi
2022-12-14 22:05:06 +13:00
parent c630c97c06
commit 2ec43e97c1
4 changed files with 247 additions and 60 deletions
+73
View File
@@ -23,6 +23,8 @@ using System.Text;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.IO.Pipes; using System.IO.Pipes;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace VRCX namespace VRCX
{ {
@@ -77,6 +79,30 @@ namespace VRCX
File.WriteAllText(configFile, json); File.WriteAllText(configFile, json);
} }
public string GetVRChatAppDataLocation()
{
var json = ReadConfigFile();
if (!string.IsNullOrEmpty(json))
{
var obj = JsonConvert.DeserializeObject<JObject>(json);
if (obj["cache_directory"] != null)
{
var cacheDir = (string)obj["cache_directory"];
if (!string.IsNullOrEmpty(cacheDir) && Directory.Exists(cacheDir))
{
return cacheDir;
}
}
}
var cachePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"Low\VRChat\VRChat";
return cachePath;
}
public string GetVRChatCacheLocation()
{
return Path.Combine(GetVRChatAppDataLocation(), "Cache-WindowsPlayer");
}
public void ShowDevTools() public void ShowDevTools()
{ {
MainForm.Instance.Browser.ShowDevTools(); MainForm.Instance.Browser.ShowDevTools();
@@ -439,6 +465,53 @@ namespace VRCX
return clipboard; return clipboard;
} }
public string GetVRChatRegistryKey(string key)
{
// https://answers.unity.com/questions/177945/playerprefs-changing-the-name-of-keys.html?childToView=208076#answer-208076
// VRC_GROUP_ORDER_usr_032383a7-748c-4fb2-94e4-bcb928e5de6b_h2810492971
uint hash = 5381;
foreach (char c in key)
hash = hash * 33 ^ c;
var keyName = key + "_h" + hash;
using (var regKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\VRChat\VRChat"))
{
var bytes = (byte[])regKey?.GetValue(keyName);
if (bytes == null)
return null;
var value = Encoding.ASCII.GetString(bytes);
return value;
}
}
public Dictionary<string, short> GetVRChatModerations(string currentUserId)
{
var filePath = Path.Combine(GetVRChatAppDataLocation(), "LocalPlayerModerations", $"{currentUserId}-show-hide-user.vrcset");
if (!File.Exists(filePath))
return null;
var output = new Dictionary<string, short>();
using (var reader = new StreamReader(filePath))
{
string line;
int index;
string userId;
short type;
while ((line = reader.ReadLine()) != null)
{
index = line.IndexOf(' ');
if (index <= 0)
continue;
userId = line.Substring(0, index);
type = short.Parse(line.Substring(line.Length - 3));
output.Add(userId, type);
}
}
return output;
}
public void SetStartup(bool enabled) public void SetStartup(bool enabled)
{ {
try try
+14 -18
View File
@@ -54,27 +54,24 @@ namespace VRCX
return versionHex.PadLeft(32, '0'); return versionHex.PadLeft(32, '0');
} }
public string GetVRChatCacheLocation(string cacheDir) public string GetVRChatCacheLocation()
{ {
var cachePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"Low\VRChat\VRChat\Cache-WindowsPlayer"; return AppApi.Instance.GetVRChatCacheLocation();
if (!string.IsNullOrEmpty(cacheDir) && Directory.Exists(cacheDir))
cachePath = Path.Combine(cacheDir, @"Cache-WindowsPlayer");
return cachePath;
} }
public string GetVRChatCacheFullLocation(string id, int version, string cacheDir) public string GetVRChatCacheFullLocation(string id, int version)
{ {
var cachePath = GetVRChatCacheLocation(cacheDir); var cachePath = GetVRChatCacheLocation();
var idHash = GetAssetId(id); var idHash = GetAssetId(id);
var versionLocation = GetAssetVersion(version); var versionLocation = GetAssetVersion(version);
return Path.Combine(cachePath, idHash, versionLocation); return Path.Combine(cachePath, idHash, versionLocation);
} }
public long[] CheckVRChatCache(string id, int version, string cacheDir) public long[] CheckVRChatCache(string id, int version)
{ {
long FileSize = -1; long FileSize = -1;
long IsLocked = 0; long IsLocked = 0;
var FullLocation = GetVRChatCacheFullLocation(id, version, cacheDir); var FullLocation = GetVRChatCacheFullLocation(id, version);
var FileLocation = Path.Combine(FullLocation, "__data"); var FileLocation = Path.Combine(FullLocation, "__data");
if (File.Exists(FileLocation)) if (File.Exists(FileLocation))
{ {
@@ -118,7 +115,6 @@ namespace VRCX
} }
catch (Exception) catch (Exception)
{ {
} }
DownloadProgress = -4; DownloadProgress = -4;
} }
@@ -159,16 +155,16 @@ namespace VRCX
DownloadProgress = -16; DownloadProgress = -16;
} }
public void DeleteCache(string cacheDir, string id, int version) public void DeleteCache(string id, int version)
{ {
var FullLocation = GetVRChatCacheFullLocation(id, version, cacheDir); var FullLocation = GetVRChatCacheFullLocation(id, version);
if (Directory.Exists(FullLocation)) if (Directory.Exists(FullLocation))
Directory.Delete(FullLocation, true); Directory.Delete(FullLocation, true);
} }
public void DeleteAllCache(string cacheDir) public void DeleteAllCache()
{ {
var cachePath = GetVRChatCacheLocation(cacheDir); var cachePath = GetVRChatCacheLocation();
if (Directory.Exists(cachePath)) if (Directory.Exists(cachePath))
{ {
Directory.Delete(cachePath, true); Directory.Delete(cachePath, true);
@@ -176,9 +172,9 @@ namespace VRCX
} }
} }
public void SweepCache(string cacheDir) public void SweepCache()
{ {
var cachePath = GetVRChatCacheLocation(cacheDir); var cachePath = GetVRChatCacheLocation();
if (!Directory.Exists(cachePath)) if (!Directory.Exists(cachePath))
return; return;
var directories = new DirectoryInfo(cachePath); var directories = new DirectoryInfo(cachePath);
@@ -205,9 +201,9 @@ namespace VRCX
} }
} }
public long GetCacheSize(string cacheDir) public long GetCacheSize()
{ {
var cachePath = GetVRChatCacheLocation(cacheDir); var cachePath = GetVRChatCacheLocation();
if (Directory.Exists(cachePath)) if (Directory.Exists(cachePath))
{ {
return DirSize(new DirectoryInfo(cachePath)); return DirSize(new DirectoryInfo(cachePath));
+130 -31
View File
@@ -2222,6 +2222,22 @@ speechSynthesis.getVoices();
} }
}); });
API.$on('INSTANCE', function (args) {
var {json} = args;
if (!json) {
return;
}
var D = $app.groupDialog;
if ($app.groupDialog.visible && $app.groupDialog.id === json.ownerId) {
for (var instance of D.instances) {
if (instance.id === json.instanceId) {
instance.occupants = json.n_users;
break;
}
}
}
});
// API: Friend // API: Friend
API.$on('FRIEND:LIST', function (args) { API.$on('FRIEND:LIST', function (args) {
@@ -2749,7 +2765,8 @@ speechSynthesis.getVoices();
for (var i = array.length - 1; i >= 0; i--) { for (var i = array.length - 1; i >= 0; i--) {
if ( if (
array[i].type === 'friendRequest' || array[i].type === 'friendRequest' ||
array[i].type === 'hiddenFriendRequest' array[i].type === 'hiddenFriendRequest' ||
array[i].type.includes('.')
) { ) {
array.splice(i, 1); array.splice(i, 1);
} }
@@ -2894,7 +2911,6 @@ speechSynthesis.getVoices();
for (var json of args.json) { for (var json of args.json) {
this.$emit('NOTIFICATION:V2', {json}); this.$emit('NOTIFICATION:V2', {json});
} }
console.log('NOTIFICATION:V2:LIST', args);
}); });
API.$on('NOTIFICATION:V2', function (args) { API.$on('NOTIFICATION:V2', function (args) {
@@ -4586,7 +4602,7 @@ speechSynthesis.getVoices();
API, API,
nextCurrentUserRefresh: 0, nextCurrentUserRefresh: 0,
nextFriendsRefresh: 0, nextFriendsRefresh: 0,
nextAppUpdateCheck: 0, nextAppUpdateCheck: 7200,
ipcTimeout: 0, ipcTimeout: 0,
nextClearVRCXCacheCheck: 0, nextClearVRCXCacheCheck: 0,
nextDiscordUpdate: 0, nextDiscordUpdate: 0,
@@ -4609,6 +4625,9 @@ speechSynthesis.getVoices();
this.appVersion = version; this.appVersion = version;
this.comapreAppVersion(); this.comapreAppVersion();
this.setBranch(); this.setBranch();
if (this.autoUpdateVRCX !== 'Off') {
this.checkForVRCXUpdate();
}
}); });
API.$on('SHOW_WORLD_DIALOG', (tag) => this.showWorldDialog(tag)); API.$on('SHOW_WORLD_DIALOG', (tag) => this.showWorldDialog(tag));
API.$on('SHOW_WORLD_DIALOG_SHORTNAME', (tag) => API.$on('SHOW_WORLD_DIALOG_SHORTNAME', (tag) =>
@@ -4942,6 +4961,7 @@ speechSynthesis.getVoices();
); );
this.applyUserDialogLocation(); this.applyUserDialogLocation();
this.applyWorldDialogInstances(); this.applyWorldDialogInstances();
this.applyGroupDialogInstances();
feeds.pendingUpdate = false; feeds.pendingUpdate = false;
}; };
@@ -8208,6 +8228,7 @@ speechSynthesis.getVoices();
$app.feedTableLookup(); $app.feedTableLookup();
// eslint-disable-next-line require-atomic-updates // eslint-disable-next-line require-atomic-updates
$app.notificationTable.data = await database.getNotifications(); $app.notificationTable.data = await database.getNotifications();
await this.refreshNotifications();
if (configRepository.getBool(`friendLogInit_${args.json.id}`)) { if (configRepository.getBool(`friendLogInit_${args.json.id}`)) {
await $app.getFriendLog(); await $app.getFriendLog();
} else { } else {
@@ -8302,6 +8323,7 @@ speechSynthesis.getVoices();
this.getCurrentInstanceUserList(); this.getCurrentInstanceUserList();
this.applyUserDialogLocation(); this.applyUserDialogLocation();
this.applyWorldDialogInstances(); this.applyWorldDialogInstances();
this.applyGroupDialogInstances();
} }
}; };
@@ -8650,6 +8672,7 @@ speechSynthesis.getVoices();
this.lastVideoUrl = ''; this.lastVideoUrl = '';
this.applyUserDialogLocation(); this.applyUserDialogLocation();
this.applyWorldDialogInstances(); this.applyWorldDialogInstances();
this.applyGroupDialogInstances();
}; };
$app.data.lastLocation$ = { $app.data.lastLocation$ = {
@@ -8910,6 +8933,7 @@ speechSynthesis.getVoices();
this.updateCurrentInstanceWorld(); this.updateCurrentInstanceWorld();
this.applyUserDialogLocation(); this.applyUserDialogLocation();
this.applyWorldDialogInstances(); this.applyWorldDialogInstances();
this.applyGroupDialogInstances();
} }
break; break;
case 'location': case 'location':
@@ -8928,6 +8952,7 @@ speechSynthesis.getVoices();
this.updateCurrentInstanceWorld(); this.updateCurrentInstanceWorld();
this.applyUserDialogLocation(); this.applyUserDialogLocation();
this.applyWorldDialogInstances(); this.applyWorldDialogInstances();
this.applyGroupDialogInstances();
} }
var L = API.parseLocation(gameLog.location); var L = API.parseLocation(gameLog.location);
var entry = { var entry = {
@@ -12243,10 +12268,12 @@ speechSynthesis.getVoices();
) { ) {
database.addNotificationToDatabase(ref); database.addNotificationToDatabase(ref);
} }
if ($app.friendLogInitStatus) {
$app.notifyMenu('notification'); $app.notifyMenu('notification');
$app.unseenNotifications.push(ref.id); $app.unseenNotifications.push(ref.id);
$app.queueNotificationNoty(ref); $app.queueNotificationNoty(ref);
} }
}
$app.notificationTable.data.push(ref); $app.notificationTable.data.push(ref);
$app.updateSharedFeed(true); $app.updateSharedFeed(true);
}); });
@@ -15674,6 +15701,14 @@ speechSynthesis.getVoices();
return; return;
} }
var instances = {}; var instances = {};
for (var instance of D.instances) {
instances[instance.tag] = {
...instance,
friendCount: 0,
users: []
};
}
if (typeof inputInstances !== 'undefined') {
for (var instance of inputInstances) { for (var instance of inputInstances) {
instances[instance.location] = { instances[instance.location] = {
id: instance.instanceId, id: instance.instanceId,
@@ -15683,6 +15718,7 @@ speechSynthesis.getVoices();
users: [] users: []
}; };
} }
}
var currentLocation = this.lastLocation.location; var currentLocation = this.lastLocation.location;
if (this.lastLocation.location === 'traveling') { if (this.lastLocation.location === 'traveling') {
currentLocation = this.lastLocationDestination; currentLocation = this.lastLocationDestination;
@@ -19545,15 +19581,6 @@ speechSynthesis.getVoices();
this.WriteVRChatConfigFile(); this.WriteVRChatConfigFile();
}; };
$app.methods.getVRChatCacheDir = async function () {
await this.readVRChatConfigFile();
var cacheDirectory = '';
if (this.VRChatConfigFile.cache_directory) {
cacheDirectory = this.VRChatConfigFile.cache_directory;
}
return cacheDirectory;
};
$app.data.VRChatResolutions = [ $app.data.VRChatResolutions = [
{name: '1280x720 (720p)', width: 1280, height: 720}, {name: '1280x720 (720p)', width: 1280, height: 720},
{name: '1920x1080 (1080p Default)', width: '', height: ''}, {name: '1920x1080 (1080p Default)', width: '', height: ''},
@@ -19702,11 +19729,10 @@ speechSynthesis.getVoices();
} }
}; };
$app.methods.checkVRChatCache = async function (ref) { $app.methods.checkVRChatCache = function (ref) {
if (!ref.unityPackages) { if (!ref.unityPackages) {
return [-1, 0]; return [-1, 0];
} }
var cacheDir = await this.getVRChatCacheDir();
var assetUrl = ''; var assetUrl = '';
for (var i = ref.unityPackages.length - 1; i > -1; i--) { for (var i = ref.unityPackages.length - 1; i > -1; i--) {
var unityPackage = ref.unityPackages[i]; var unityPackage = ref.unityPackages[i];
@@ -19723,7 +19749,7 @@ speechSynthesis.getVoices();
if (!id || !version) { if (!id || !version) {
return [-1, 0]; return [-1, 0];
} }
return AssetBundleCacher.CheckVRChatCache(id, version, cacheDir); return AssetBundleCacher.CheckVRChatCache(id, version);
}; };
API.getBundles = function (fileId) { API.getBundles = function (fileId) {
@@ -19858,7 +19884,6 @@ speechSynthesis.getVoices();
}; };
$app.methods.deleteVRChatCache = async function (ref) { $app.methods.deleteVRChatCache = async function (ref) {
var cacheDir = await this.getVRChatCacheDir();
var assetUrl = ''; var assetUrl = '';
for (var i = ref.unityPackages.length - 1; i > -1; i--) { for (var i = ref.unityPackages.length - 1; i > -1; i--) {
var unityPackage = ref.unityPackages[i]; var unityPackage = ref.unityPackages[i];
@@ -19872,7 +19897,7 @@ speechSynthesis.getVoices();
} }
var id = extractFileId(assetUrl); var id = extractFileId(assetUrl);
var version = parseInt(extractFileVersion(assetUrl), 10); var version = parseInt(extractFileVersion(assetUrl), 10);
await AssetBundleCacher.DeleteCache(cacheDir, id, version); await AssetBundleCacher.DeleteCache(id, version);
this.getVRChatCacheSize(); this.getVRChatCacheSize();
this.updateVRChatWorldCache(); this.updateVRChatWorldCache();
this.updateVRChatAvatarCache(); this.updateVRChatAvatarCache();
@@ -19892,8 +19917,7 @@ speechSynthesis.getVoices();
}; };
$app.methods.deleteAllVRChatCache = async function () { $app.methods.deleteAllVRChatCache = async function () {
var cacheDir = await this.getVRChatCacheDir(); await AssetBundleCacher.DeleteAllCache();
await AssetBundleCacher.DeleteAllCache(cacheDir);
this.getVRChatCacheSize(); this.getVRChatCacheSize();
}; };
@@ -19904,8 +19928,7 @@ speechSynthesis.getVoices();
}; };
$app.methods.sweepVRChatCache = async function () { $app.methods.sweepVRChatCache = async function () {
var cacheDir = await this.getVRChatCacheDir(); await AssetBundleCacher.SweepCache();
await AssetBundleCacher.SweepCache(cacheDir);
if (this.VRChatConfigDialog.visible) { if (this.VRChatConfigDialog.visible) {
this.getVRChatCacheSize(); this.getVRChatCacheSize();
} }
@@ -19917,13 +19940,12 @@ speechSynthesis.getVoices();
$app.methods.getVRChatCacheSize = async function () { $app.methods.getVRChatCacheSize = async function () {
this.VRChatCacheSizeLoading = true; this.VRChatCacheSizeLoading = true;
var cacheDir = await this.getVRChatCacheDir();
var totalCacheSize = 20; var totalCacheSize = 20;
if (this.VRChatConfigFile.cache_size) { if (this.VRChatConfigFile.cache_size) {
totalCacheSize = this.VRChatConfigFile.cache_size; totalCacheSize = this.VRChatConfigFile.cache_size;
} }
this.VRChatTotalCacheSize = totalCacheSize; this.VRChatTotalCacheSize = totalCacheSize;
var usedCacheSize = await AssetBundleCacher.GetCacheSize(cacheDir); var usedCacheSize = await AssetBundleCacher.GetCacheSize();
this.VRChatUsedCacheSize = (usedCacheSize / 1073741824).toFixed(2); this.VRChatUsedCacheSize = (usedCacheSize / 1073741824).toFixed(2);
this.VRChatCacheSizeLoading = false; this.VRChatCacheSizeLoading = false;
}; };
@@ -19975,16 +19997,13 @@ speechSynthesis.getVoices();
} }
var fileId = extractFileId(assetUrl); var fileId = extractFileId(assetUrl);
var fileVersion = parseInt(extractFileVersion(assetUrl), 10); var fileVersion = parseInt(extractFileVersion(assetUrl), 10);
var cacheDir = await this.getVRChatCacheDir();
var assetLocation = await AssetBundleCacher.GetVRChatCacheFullLocation( var assetLocation = await AssetBundleCacher.GetVRChatCacheFullLocation(
fileId, fileId,
fileVersion, fileVersion
cacheDir
); );
var cacheInfo = await AssetBundleCacher.CheckVRChatCache( var cacheInfo = await AssetBundleCacher.CheckVRChatCache(
fileId, fileId,
fileVersion, fileVersion
cacheDir
); );
var inCache = false; var inCache = false;
if (cacheInfo[0] > 0) { if (cacheInfo[0] > 0) {
@@ -20142,6 +20161,33 @@ speechSynthesis.getVoices();
} }
} }
this.userDialog.isGroupsLoading = false; this.userDialog.isGroupsLoading = false;
if (userId === API.currentUser.id) {
this.sortCurrentUserGroups();
}
};
$app.methods.sortCurrentUserGroups = function () {
var groupList = [];
var sortGroups = function (a, b) {
var aIndex = groupList.indexOf(a.id);
var bIndex = groupList.indexOf(b.id);
if (aIndex === -1 && bIndex === -1) {
return 0;
}
if (aIndex === -1) {
return 1;
}
if (bIndex === -1) {
return -1;
}
return aIndex - bIndex;
};
AppApi.GetVRChatRegistryKey(
`VRC_GROUP_ORDER_${API.currentUser.id}`
).then((json) => {
groupList = JSON.parse(json);
this.userGroups.remainingGroups.sort(sortGroups);
});
}; };
// gallery // gallery
@@ -20585,7 +20631,9 @@ speechSynthesis.getVoices();
} }
this.notifyMenu('settings'); this.notifyMenu('settings');
var type = 'Auto'; var type = 'Auto';
if (this.autoUpdateVRCX === 'Notify') { if (!API.isLoggedIn) {
this.showVRCXUpdateDialog();
} else if (this.autoUpdateVRCX === 'Notify') {
this.showVRCXUpdateDialog(); this.showVRCXUpdateDialog();
} else if (this.autoUpdateVRCX === 'Auto Download') { } else if (this.autoUpdateVRCX === 'Auto Download') {
var autoInstall = false; var autoInstall = false;
@@ -23210,6 +23258,30 @@ speechSynthesis.getVoices();
} }
}); });
/*
params: {
groupId: string
}
*/
API.getGroupRoles = function (params) {
return this.call(`groups/${params.groupId}/roles`, {
method: 'GET',
params
}).then((json) => {
var args = {
json,
params
};
this.$emit('GROUP:ROLES', args);
return args;
});
};
API.$on('GROUP:ROLES', function (args) {
console.log(args);
});
/* /*
params: { params: {
groupId: string groupId: string
@@ -23342,7 +23414,9 @@ speechSynthesis.getVoices();
ref: {}, ref: {},
announcement: {}, announcement: {},
members: [], members: [],
instances: [] instances: [],
roles: [],
memberRoles: []
}; };
$app.methods.showGroupDialog = function (groupId) { $app.methods.showGroupDialog = function (groupId) {
@@ -23360,6 +23434,8 @@ speechSynthesis.getVoices();
D.treeData = []; D.treeData = [];
D.announcement = {}; D.announcement = {};
D.instances = []; D.instances = [];
D.roles = [];
D.memberRoles = [];
if (this.groupDialogLastMembers !== groupId) { if (this.groupDialogLastMembers !== groupId) {
D.members = []; D.members = [];
} }
@@ -23436,6 +23512,23 @@ speechSynthesis.getVoices();
this.applyGroupDialogInstances(args3.json); this.applyGroupDialogInstances(args3.json);
} }
}); });
API.getGroupRoles({
groupId
}).then((args4) => {
if (groupId === args4.params.groupId) {
D.roles = args4.json;
for (var role of args4.json) {
if (
D.ref &&
D.ref.myMember &&
Array.isArray(D.ref.myMember.roleIds) &&
D.ref.myMember.roleIds.includes(role.id)
) {
D.memberRoles.push(role);
}
}
}
});
} }
if (this.$refs.groupDialogTabs.currentName === '0') { if (this.$refs.groupDialogTabs.currentName === '0') {
this.groupDialogLastActiveTab = 'Info'; this.groupDialogLastActiveTab = 'Info';
@@ -23505,7 +23598,13 @@ speechSynthesis.getVoices();
$app.methods.refreshGroupDialogTreeData = function () { $app.methods.refreshGroupDialogTreeData = function () {
var D = this.groupDialog; var D = this.groupDialog;
D.treeData = buildTreeData(D.ref); D.treeData = buildTreeData({
group: D.ref,
announcement: D.announcement,
roles: D.roles,
instances: D.instances,
members: D.members
});
}; };
$app.methods.joinGroup = function (groupId) { $app.methods.joinGroup = function (groupId) {
+20 -1
View File
@@ -871,7 +871,7 @@ html
el-tooltip(placement="top" content="Refresh" :disabled="hideTooltips") el-tooltip(placement="top" content="Refresh" :disabled="hideTooltips")
el-button(type="default" @click="API.getConfig()" size="mini" icon="el-icon-refresh" circle style="margin-left:5px") el-button(type="default" @click="API.getConfig()" size="mini" icon="el-icon-refresh" circle style="margin-left:5px")
.x-friend-list(style="margin-top:10px") .x-friend-list(style="margin-top:10px")
.x-friend-item(v-for="(link, item) in API.cachedConfig.downloadUrls" :key="item" v-if="item !== 'sdk2'" placement="top") .x-friend-item(v-for="(link, item) in API.cachedConfig.downloadUrls" :key="item" placement="top")
.detail(@click="openExternalLink(link)") .detail(@click="openExternalLink(link)")
span.name(v-text="item") span.name(v-text="item")
span.extra(v-text="link") span.extra(v-text="link")
@@ -2334,6 +2334,25 @@ html
.detail .detail
span.name Joined At span.name Joined At
span.extra {{ groupDialog.ref.myMember.joinedAt | formatDate('long') }} span.extra {{ groupDialog.ref.myMember.joinedAt | formatDate('long') }}
.x-friend-item(style="cursor:default")
.detail
span.name Roles
span.extra(v-if="groupDialog.memberRoles.length === 0") -
span.extra(v-else)
template(v-for="(role, rIndex) in groupDialog.memberRoles" :key="rIndex")
el-tooltip(placement="top")
template(#content)
span Description: {{ role.description }}
br
span(v-if="role.updatedAt") Updated At: {{ role.updatedAt | formatDate('long') }}
span(v-else) Created At: {{ role.createdAt | formatDate('long') }}
br
span Permissions:
br
template(v-for="(permission, pIndex) in role.permissions" :key="pIndex")
span {{ permission }}
br
span {{ role.name }}{{ rIndex < groupDialog.memberRoles.length - 1 ? ', ' : '' }}
el-tab-pane(label="Members") el-tab-pane(label="Members")
template(v-if="groupDialog.visible && groupDialog.ref.membershipStatus === 'member'") template(v-if="groupDialog.visible && groupDialog.ref.membershipStatus === 'member'")
span(v-if="hasGroupPermission(groupDialog.ref, 'group-members-viewall')" style="font-weight:bold;font-size:16px") All Members span(v-if="hasGroupPermission(groupDialog.ref, 'group-members-viewall')" style="font-weight:bold;font-size:16px") All Members