mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-07 06:56:04 +02:00
Merge branch 'GameLogSQLite'
This commit is contained in:
@@ -229,20 +229,15 @@ namespace VRCX
|
|||||||
return CpuMonitor.Instance.CpuUsage;
|
return CpuMonitor.Instance.CpuUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CacheImage(string Base64File)
|
public void DesktopNotification(string BoldText, string Text, string Image)
|
||||||
{
|
|
||||||
String Icon = Path.Combine(Program.AppDataDirectory, "cache\\toast");
|
|
||||||
File.WriteAllBytes(Icon, Convert.FromBase64String(Base64File));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DesktopNotification(string BoldText, string Text, bool Image)
|
|
||||||
{
|
{
|
||||||
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText02);
|
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText02);
|
||||||
XmlNodeList stringElements = toastXml.GetElementsByTagName("text");
|
XmlNodeList stringElements = toastXml.GetElementsByTagName("text");
|
||||||
String imagePath = Path.Combine(Program.BaseDirectory, "VRCX.ico");
|
String imagePath = Path.Combine(Program.BaseDirectory, "VRCX.ico");
|
||||||
if (Image)
|
if (!String.IsNullOrEmpty(Image))
|
||||||
{
|
{
|
||||||
imagePath = Path.Combine(Program.AppDataDirectory, "cache\\toast");
|
imagePath = Path.Combine(Program.AppDataDirectory, "cache\\toast");
|
||||||
|
File.WriteAllBytes(imagePath, Convert.FromBase64String(Image));
|
||||||
}
|
}
|
||||||
stringElements[0].AppendChild(toastXml.CreateTextNode(BoldText));
|
stringElements[0].AppendChild(toastXml.CreateTextNode(BoldText));
|
||||||
stringElements[1].AppendChild(toastXml.CreateTextNode(Text));
|
stringElements[1].AppendChild(toastXml.CreateTextNode(Text));
|
||||||
@@ -268,14 +263,20 @@ namespace VRCX
|
|||||||
public string sourceApp { get; set; }
|
public string sourceApp { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void XSNotification(string Title, string Content, int Timeout, bool Image)
|
public void XSNotification(string Title, string Content, int Timeout, string Image)
|
||||||
{
|
{
|
||||||
bool UseBase64Icon = true;
|
bool UseBase64Icon;
|
||||||
String Icon = "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsTAAALEwEAmpwYAAAHaGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIxLTA0LTA4VDE0OjU3OjAxKzEyOjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMS0wNC0wOFQxNjozMzoxMCsxMjowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMS0wNC0wOFQxNjozMzoxMCsxMjowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo2YTY5MmQzYi03ZTJkLTNiNGUtYTMzZC1hN2MwOTNlOGU0OTkiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDo1NTE2MWIyMi1hYzgxLTY3NDYtODAyYi1kODIzYWFmN2RjYjciIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3ZjJjNTA2ZS02YTVhLWRhNGEtOTg5Mi02NDZiMzQ0MGQxZTgiPiA8cGhvdG9zaG9wOkRvY3VtZW50QW5jZXN0b3JzPiA8cmRmOkJhZz4gPHJkZjpsaT5hZG9iZTpkb2NpZDpwaG90b3Nob3A6NmJmOGE5MTgtY2QzZS03OTRjLTk3NzktMzM0YjYwZWJiNTYyPC9yZGY6bGk+IDwvcmRmOkJhZz4gPC9waG90b3Nob3A6RG9jdW1lbnRBbmNlc3RvcnM+IDx4bXBNTTpIaXN0b3J5PiA8cmRmOlNlcT4gPHJkZjpsaSBzdEV2dDphY3Rpb249ImNyZWF0ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6N2YyYzUwNmUtNmE1YS1kYTRhLTk4OTItNjQ2YjM0NDBkMWU4IiBzdEV2dDp3aGVuPSIyMDIxLTA0LTA4VDE0OjU3OjAxKzEyOjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOmJhM2ZjODI3LTM0ZjQtYjU0OC05ZGFiLTZhMTZlZmQzZjAxMSIgc3RFdnQ6d2hlbj0iMjAyMS0wNC0wOFQxNTowMTozMSsxMjowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiBzdEV2dDpjaGFuZ2VkPSIvIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo2YTY5MmQzYi03ZTJkLTNiNGUtYTMzZC1hN2MwOTNlOGU0OTkiIHN0RXZ0OndoZW49IjIwMjEtMDQtMDhUMTY6MzM6MTArMTI6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4XAd9sAAAFM0lEQVR42u2aWUhjVxjHjVpf3Iraoh3c4ksFx7ZYahV8EHEBqdQHFdsHQRRxpcyDIDNFpdSK+iBKUcTpmy/iglVrtT4oYsEq7hP3RGXcqqY6invy9Xy3OdPEE5PY5pKb5P7hTyA5y/1+Ofc7y70OAOBgz3YQAYgARAAiABGACEAEIAIQAYgADBT6V4HErcRbxCAwy4nriN/DC+UDADb8swADv++fiN3MDeAJ8be0k9HRUbi4uACUWq22qFFvzt5AZ1enNoSvzJ4DiJ5j412dXSBUVf9QTQH08gHgF2x8b2/P0nGqNGa0ML9AAazyAeA3bPzg4MDoFV5fX8PZ2RlcXl7qGL83JjKsVeT2UpHyaqxzdXXFtUVvOVpMYx3JFfK3CZEPAL9i4/v7+0aDwDL5+fmQl5cHBQUFnHNzc6GsrAzW19cNBQ8dHR3q7OxsFamvxnrFxcWQnp4O4+PjRvtdW1ujANYtCgBVWlqqN0vn5ORw/6o+TU1Nga+vL1MnMTERtre3rQvA3d0dZGZmMsG4ublBW1sbU/7k5ATi4+OZ8uHh4bC5uWlSn4ICQC/I39+fCSo0NBRWV1d1M3h1NVPOw8MDenp6HtWfoACg8N92dnZmgisqKuISI2pkZAS8vLyYMngb3dzcWDcAvBUKCwuZ4FxdXWFwcJDLB1FRUczvcXFxcHx8/Ki+BAkAtbW1BZGRkUyQsbGx3Gzh5OSk831QUJBJWd9qAKD6+/vB29tbJ1CJRMIE7+7uDk1NTf+pD0EDwFuhoqKCC9rQZiYrKwtub29tDwBqZ2cHUlNTwdHRkQkcwURHRxtcKFk9ANTAwAB4enoyAHCmqKys/F9tCx4ATnuY9B4a/mFhYTA3N2e7AFpaWoweaKSkpHCbH5sDMDMzw01vxgC4uLhAfX29oAHo3Yoa0vn5OSQnJzPBZmRkQFpaGjMz+Pn5wdjYmGAB3D0WQG1tLRM8Bjk7OwsKhQICAwOZ3xMSEkw6e7AEANVjAAwPD3ObmvsBVlVVgUr1z8FOQ0MD8zsukMrLyx+1JhBcDtjd3YWIiAgmOLwdtP9dTHpJSUl6d4M4bVolADzdKSkpYYIKCAjgdn/3NT8/Dz4+Pkz5mJgYkw5DBAUAh3ZzczOzDcYVYE1NzYNL5bq6Or1LZVw7nJ6eWg8APMHBRQ0ehkilUggODuaSHp4QGdriHh0dcTMDlsV6ISEhXF0cGb29vRYHMGTqqTCWmZiYgKWlJVheXgaZTMatAw4PD43WVSqVMD09zdVD48kRtiWXy98mzYe0Id+gADb4ADCMjSuPlYJ9MKLYVFAAm3wAaMbGFxcXBQugu7ubAviDDwCfY+N4Ro/DVGjCmUIrcX7P1+PxfdpJ68tWGBoagr7+PrMZH3DiwglnBGPCtQOWxeSIM45W8IvEUr4AfEG8xPcj7sbGRqMAVpZX9NWdIv6Ur/cDqD4k/o64j/h34jEzeUTTHhdMX2+fQQCyVzIa9KXmwe0z4hB6kXwCQL2DLyEQ+xK/byZ7EfsRN1AICwsLDwLAKVZTDkfkZ8RO2hfINwA+9YQ+iUYf/nloDADe80/vN2LNAFCRxGsYx4vnL/QmRS0Ar4g/sjUAqC/pKGhvb7dLAKhyCmFyctIuAbxL3EEhaL+eowVARvyxrQJASYlnKAS6IbInAKg44lMKAYU7Ra1p8BNbB4D6hvgGY8MlMG6PNQBWiCPsAYAL8Y96lr+4ivzAHgDQpPiS+EwikfxFPl8Tf00s4RWA+Lq8CEAEIAIQAYgARAA26b8BaVJkoY+4rDoAAAAASUVORK5CYII=";
|
string Icon;
|
||||||
if (Image)
|
if (String.IsNullOrEmpty(Image))
|
||||||
|
{
|
||||||
|
UseBase64Icon = true;
|
||||||
|
Icon = "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsTAAALEwEAmpwYAAAHaGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIxLTA0LTA4VDE0OjU3OjAxKzEyOjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMS0wNC0wOFQxNjozMzoxMCsxMjowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMS0wNC0wOFQxNjozMzoxMCsxMjowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo2YTY5MmQzYi03ZTJkLTNiNGUtYTMzZC1hN2MwOTNlOGU0OTkiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDo1NTE2MWIyMi1hYzgxLTY3NDYtODAyYi1kODIzYWFmN2RjYjciIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3ZjJjNTA2ZS02YTVhLWRhNGEtOTg5Mi02NDZiMzQ0MGQxZTgiPiA8cGhvdG9zaG9wOkRvY3VtZW50QW5jZXN0b3JzPiA8cmRmOkJhZz4gPHJkZjpsaT5hZG9iZTpkb2NpZDpwaG90b3Nob3A6NmJmOGE5MTgtY2QzZS03OTRjLTk3NzktMzM0YjYwZWJiNTYyPC9yZGY6bGk+IDwvcmRmOkJhZz4gPC9waG90b3Nob3A6RG9jdW1lbnRBbmNlc3RvcnM+IDx4bXBNTTpIaXN0b3J5PiA8cmRmOlNlcT4gPHJkZjpsaSBzdEV2dDphY3Rpb249ImNyZWF0ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6N2YyYzUwNmUtNmE1YS1kYTRhLTk4OTItNjQ2YjM0NDBkMWU4IiBzdEV2dDp3aGVuPSIyMDIxLTA0LTA4VDE0OjU3OjAxKzEyOjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOmJhM2ZjODI3LTM0ZjQtYjU0OC05ZGFiLTZhMTZlZmQzZjAxMSIgc3RFdnQ6d2hlbj0iMjAyMS0wNC0wOFQxNTowMTozMSsxMjowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiBzdEV2dDpjaGFuZ2VkPSIvIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo2YTY5MmQzYi03ZTJkLTNiNGUtYTMzZC1hN2MwOTNlOGU0OTkiIHN0RXZ0OndoZW49IjIwMjEtMDQtMDhUMTY6MzM6MTArMTI6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4XAd9sAAAFM0lEQVR42u2aWUhjVxjHjVpf3Iraoh3c4ksFx7ZYahV8EHEBqdQHFdsHQRRxpcyDIDNFpdSK+iBKUcTpmy/iglVrtT4oYsEq7hP3RGXcqqY6invy9Xy3OdPEE5PY5pKb5P7hTyA5y/1+Ofc7y70OAOBgz3YQAYgARAAiABGACEAEIAIQAYgADBT6V4HErcRbxCAwy4nriN/DC+UDADb8swADv++fiN3MDeAJ8be0k9HRUbi4uACUWq22qFFvzt5AZ1enNoSvzJ4DiJ5j412dXSBUVf9QTQH08gHgF2x8b2/P0nGqNGa0ML9AAazyAeA3bPzg4MDoFV5fX8PZ2RlcXl7qGL83JjKsVeT2UpHyaqxzdXXFtUVvOVpMYx3JFfK3CZEPAL9i4/v7+0aDwDL5+fmQl5cHBQUFnHNzc6GsrAzW19cNBQ8dHR3q7OxsFamvxnrFxcWQnp4O4+PjRvtdW1ujANYtCgBVWlqqN0vn5ORw/6o+TU1Nga+vL1MnMTERtre3rQvA3d0dZGZmMsG4ublBW1sbU/7k5ATi4+OZ8uHh4bC5uWlSn4ICQC/I39+fCSo0NBRWV1d1M3h1NVPOw8MDenp6HtWfoACg8N92dnZmgisqKuISI2pkZAS8vLyYMngb3dzcWDcAvBUKCwuZ4FxdXWFwcJDLB1FRUczvcXFxcHx8/Ki+BAkAtbW1BZGRkUyQsbGx3Gzh5OSk831QUJBJWd9qAKD6+/vB29tbJ1CJRMIE7+7uDk1NTf+pD0EDwFuhoqKCC9rQZiYrKwtub29tDwBqZ2cHUlNTwdHRkQkcwURHRxtcKFk9ANTAwAB4enoyAHCmqKys/F9tCx4ATnuY9B4a/mFhYTA3N2e7AFpaWoweaKSkpHCbH5sDMDMzw01vxgC4uLhAfX29oAHo3Yoa0vn5OSQnJzPBZmRkQFpaGjMz+Pn5wdjYmGAB3D0WQG1tLRM8Bjk7OwsKhQICAwOZ3xMSEkw6e7AEANVjAAwPD3ObmvsBVlVVgUr1z8FOQ0MD8zsukMrLyx+1JhBcDtjd3YWIiAgmOLwdtP9dTHpJSUl6d4M4bVolADzdKSkpYYIKCAjgdn/3NT8/Dz4+Pkz5mJgYkw5DBAUAh3ZzczOzDcYVYE1NzYNL5bq6Or1LZVw7nJ6eWg8APMHBRQ0ehkilUggODuaSHp4QGdriHh0dcTMDlsV6ISEhXF0cGb29vRYHMGTqqTCWmZiYgKWlJVheXgaZTMatAw4PD43WVSqVMD09zdVD48kRtiWXy98mzYe0Id+gADb4ADCMjSuPlYJ9MKLYVFAAm3wAaMbGFxcXBQugu7ubAviDDwCfY+N4Ro/DVGjCmUIrcX7P1+PxfdpJ68tWGBoagr7+PrMZH3DiwglnBGPCtQOWxeSIM45W8IvEUr4AfEG8xPcj7sbGRqMAVpZX9NWdIv6Ur/cDqD4k/o64j/h34jEzeUTTHhdMX2+fQQCyVzIa9KXmwe0z4hB6kXwCQL2DLyEQ+xK/byZ7EfsRN1AICwsLDwLAKVZTDkfkZ8RO2hfINwA+9YQ+iUYf/nloDADe80/vN2LNAFCRxGsYx4vnL/QmRS0Ar4g/sjUAqC/pKGhvb7dLAKhyCmFyctIuAbxL3EEhaL+eowVARvyxrQJASYlnKAS6IbInAKg44lMKAYU7Ra1p8BNbB4D6hvgGY8MlMG6PNQBWiCPsAYAL8Y96lr+4ivzAHgDQpPiS+EwikfxFPl8Tf00s4RWA+Lq8CEAEIAIQAYgARAA26b8BaVJkoY+4rDoAAAAASUVORK5CYII=";
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
UseBase64Icon = false;
|
UseBase64Icon = false;
|
||||||
Icon = Path.Combine(Program.AppDataDirectory, "cache\\toast");
|
Icon = Path.Combine(Program.AppDataDirectory, "cache\\toast");
|
||||||
|
File.WriteAllBytes(Icon, Convert.FromBase64String(Image));
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress broadcastIP = IPAddress.Parse("127.0.0.1");
|
IPAddress broadcastIP = IPAddress.Parse("127.0.0.1");
|
||||||
@@ -314,13 +315,28 @@ namespace VRCX
|
|||||||
System.Environment.Exit(0);
|
System.Environment.Exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool checkForUpdateZip()
|
public bool CheckForUpdateZip()
|
||||||
{
|
{
|
||||||
if (File.Exists(Path.Combine(Program.AppDataDirectory, "update.exe")))
|
if (File.Exists(Path.Combine(Program.AppDataDirectory, "update.exe")))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ExecuteAppFunction(string function, string json)
|
||||||
|
{
|
||||||
|
MainForm.Instance.Browser.ExecuteScriptAsync($"$app.{function}", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExecuteVrFeedFunction(string function, string json)
|
||||||
|
{
|
||||||
|
VRCXVR._browser1.ExecuteScriptAsync($"$app.{function}", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExecuteVrOverlayFunction(string function, string json)
|
||||||
|
{
|
||||||
|
VRCXVR._browser2.ExecuteScriptAsync($"$app.{function}", json);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetStartup(bool enabled)
|
public void SetStartup(bool enabled)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
+28
-5
@@ -1,4 +1,4 @@
|
|||||||
// Copyright(c) 2019 pypy. All rights reserved.
|
// Copyright(c) 2019 pypy. All rights reserved.
|
||||||
//
|
//
|
||||||
// This work is licensed under the terms of the MIT license.
|
// This work is licensed under the terms of the MIT license.
|
||||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||||
@@ -17,6 +17,7 @@ namespace VRCX
|
|||||||
private DiscordRpcClient m_Client;
|
private DiscordRpcClient m_Client;
|
||||||
private Timer m_Timer;
|
private Timer m_Timer;
|
||||||
private bool m_Active;
|
private bool m_Active;
|
||||||
|
public static string DiscordAppId;
|
||||||
|
|
||||||
static Discord()
|
static Discord()
|
||||||
{
|
{
|
||||||
@@ -78,7 +79,7 @@ namespace VRCX
|
|||||||
{
|
{
|
||||||
if (m_Client == null)
|
if (m_Client == null)
|
||||||
{
|
{
|
||||||
m_Client = new DiscordRpcClient("525953831020920832");
|
m_Client = new DiscordRpcClient(DiscordAppId);
|
||||||
if (m_Client.Initialize() == false)
|
if (m_Client.Initialize() == false)
|
||||||
{
|
{
|
||||||
m_Client.Dispose();
|
m_Client.Dispose();
|
||||||
@@ -126,7 +127,7 @@ namespace VRCX
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAssets(string largeKey, string largeText, string smallKey, string smallText)
|
public void SetAssets(string largeKey, string largeText, string smallKey, string smallText, string partyId, int partySize, int partyMax, string buttonText, string buttonUrl, string appId)
|
||||||
{
|
{
|
||||||
m_Lock.EnterWriteLock();
|
m_Lock.EnterWriteLock();
|
||||||
try
|
try
|
||||||
@@ -139,13 +140,35 @@ namespace VRCX
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_Presence.Assets == null)
|
if (m_Presence.Assets == null)
|
||||||
{
|
|
||||||
m_Presence.Assets = new Assets();
|
m_Presence.Assets = new Assets();
|
||||||
}
|
if (m_Presence.Party == null)
|
||||||
|
m_Presence.Party = new Party();
|
||||||
m_Presence.Assets.LargeImageKey = largeKey;
|
m_Presence.Assets.LargeImageKey = largeKey;
|
||||||
m_Presence.Assets.LargeImageText = largeText;
|
m_Presence.Assets.LargeImageText = largeText;
|
||||||
m_Presence.Assets.SmallImageKey = smallKey;
|
m_Presence.Assets.SmallImageKey = smallKey;
|
||||||
m_Presence.Assets.SmallImageText = smallText;
|
m_Presence.Assets.SmallImageText = smallText;
|
||||||
|
m_Presence.Party.ID = partyId;
|
||||||
|
m_Presence.Party.Size = partySize;
|
||||||
|
m_Presence.Party.Max = partyMax;
|
||||||
|
Button[] Buttons = { };
|
||||||
|
if (!string.IsNullOrEmpty(buttonUrl))
|
||||||
|
{
|
||||||
|
Buttons = new Button[]
|
||||||
|
{
|
||||||
|
new Button() { Label = buttonText, Url = buttonUrl }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
m_Presence.Buttons = Buttons;
|
||||||
|
if (DiscordAppId != appId)
|
||||||
|
{
|
||||||
|
DiscordAppId = appId;
|
||||||
|
if (m_Client != null)
|
||||||
|
{
|
||||||
|
m_Client.Dispose();
|
||||||
|
m_Client = null;
|
||||||
|
}
|
||||||
|
Update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|||||||
+92
-21
@@ -3,6 +3,7 @@
|
|||||||
// This work is licensed under the terms of the MIT license.
|
// This work is licensed under the terms of the MIT license.
|
||||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||||
|
|
||||||
|
using CefSharp;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@@ -30,6 +31,8 @@ namespace VRCX
|
|||||||
private readonly List<string[]> m_LogList;
|
private readonly List<string[]> m_LogList;
|
||||||
private Thread m_Thread;
|
private Thread m_Thread;
|
||||||
private bool m_ResetLog;
|
private bool m_ResetLog;
|
||||||
|
private bool m_FirstRun = true;
|
||||||
|
private static DateTime tillDate = DateTime.Now;
|
||||||
|
|
||||||
// NOTE
|
// NOTE
|
||||||
// FileSystemWatcher() is unreliable
|
// FileSystemWatcher() is unreliable
|
||||||
@@ -65,6 +68,17 @@ namespace VRCX
|
|||||||
thread.Join();
|
thread.Join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
m_ResetLog = true;
|
||||||
|
m_Thread?.Interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetDateTill(string date)
|
||||||
|
{
|
||||||
|
tillDate = DateTime.Parse(date);
|
||||||
|
}
|
||||||
|
|
||||||
private void ThreadLoop()
|
private void ThreadLoop()
|
||||||
{
|
{
|
||||||
while (m_Thread != null)
|
while (m_Thread != null)
|
||||||
@@ -86,6 +100,7 @@ namespace VRCX
|
|||||||
{
|
{
|
||||||
if (m_ResetLog == true)
|
if (m_ResetLog == true)
|
||||||
{
|
{
|
||||||
|
m_FirstRun = true;
|
||||||
m_ResetLog = false;
|
m_ResetLog = false;
|
||||||
m_LogContextMap.Clear();
|
m_LogContextMap.Clear();
|
||||||
m_LogListLock.EnterWriteLock();
|
m_LogListLock.EnterWriteLock();
|
||||||
@@ -109,26 +124,17 @@ namespace VRCX
|
|||||||
// sort by creation time
|
// sort by creation time
|
||||||
Array.Sort(fileInfos, (a, b) => a.CreationTimeUtc.CompareTo(b.CreationTimeUtc));
|
Array.Sort(fileInfos, (a, b) => a.CreationTimeUtc.CompareTo(b.CreationTimeUtc));
|
||||||
|
|
||||||
var utcNow = DateTime.UtcNow;
|
|
||||||
var minLimitDateTime = utcNow.AddDays(-7d);
|
|
||||||
var minRefreshDateTime = utcNow.AddMinutes(-3d);
|
|
||||||
|
|
||||||
foreach (var fileInfo in fileInfos)
|
foreach (var fileInfo in fileInfos)
|
||||||
{
|
|
||||||
var lastWriteTimeUtc = fileInfo.LastWriteTimeUtc;
|
|
||||||
|
|
||||||
if (lastWriteTimeUtc < minLimitDateTime)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastWriteTimeUtc >= minRefreshDateTime)
|
|
||||||
{
|
{
|
||||||
fileInfo.Refresh();
|
fileInfo.Refresh();
|
||||||
if (fileInfo.Exists == false)
|
if (fileInfo.Exists == false)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DateTime.Compare(fileInfo.LastWriteTime, tillDate) < 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_LogContextMap.TryGetValue(fileInfo.Name, out LogContext logContext) == true)
|
if (m_LogContextMap.TryGetValue(fileInfo.Name, out LogContext logContext) == true)
|
||||||
@@ -155,6 +161,8 @@ namespace VRCX
|
|||||||
{
|
{
|
||||||
m_LogContextMap.Remove(name);
|
m_LogContextMap.Remove(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_FirstRun = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ParseLog(FileInfo fileInfo, LogContext logContext)
|
private void ParseLog(FileInfo fileInfo, LogContext logContext)
|
||||||
@@ -184,17 +192,33 @@ namespace VRCX
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DateTime.TryParseExact(
|
||||||
|
line.Substring(0, 19),
|
||||||
|
"yyyy.MM.dd HH:mm:ss",
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
DateTimeStyles.AssumeLocal,
|
||||||
|
out DateTime lineDate
|
||||||
|
))
|
||||||
|
{
|
||||||
|
if (DateTime.Compare(lineDate, tillDate) <= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var offset = 34;
|
var offset = 34;
|
||||||
if (line[offset] == '[')
|
if (line[offset] == '[')
|
||||||
{
|
{
|
||||||
if (ParseLogOnPlayerJoinedOrLeft(fileInfo, logContext, line, offset) == true ||
|
if (ParseLogOnPlayerJoinedOrLeft(fileInfo, logContext, line, offset) == true ||
|
||||||
ParseLogLocation(fileInfo, logContext, line, offset) == true ||
|
ParseLogLocation(fileInfo, logContext, line, offset) == true ||
|
||||||
|
ParseLogLocationDestination(fileInfo, logContext, line, offset) == true ||
|
||||||
ParseLogPortalSpawn(fileInfo, logContext, line, offset) == true ||
|
ParseLogPortalSpawn(fileInfo, logContext, line, offset) == true ||
|
||||||
ParseLogNotification(fileInfo, logContext, line, offset) == true ||
|
ParseLogNotification(fileInfo, logContext, line, offset) == true ||
|
||||||
ParseLogJoinBlocked(fileInfo, logContext, line, offset) == true ||
|
ParseLogJoinBlocked(fileInfo, logContext, line, offset) == true ||
|
||||||
ParseLogAvatarPedestalChange(fileInfo, logContext, line, offset) == true ||
|
ParseLogAvatarPedestalChange(fileInfo, logContext, line, offset) == true ||
|
||||||
ParseLogVideoError(fileInfo, logContext, line, offset) == true ||
|
ParseLogVideoError(fileInfo, logContext, line, offset) == true ||
|
||||||
ParseLogVideoPlay(fileInfo, logContext, line, offset) == true)
|
ParseLogVideoPlay(fileInfo, logContext, line, offset) == true ||
|
||||||
|
ParseLogWorldVRCX(fileInfo, logContext, line, offset) == true)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -221,6 +245,12 @@ namespace VRCX
|
|||||||
m_LogListLock.EnterWriteLock();
|
m_LogListLock.EnterWriteLock();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (!m_FirstRun)
|
||||||
|
{
|
||||||
|
var logLine = System.Text.Json.JsonSerializer.Serialize(item);
|
||||||
|
if (MainForm.Instance != null && MainForm.Instance.Browser != null)
|
||||||
|
MainForm.Instance.Browser.ExecuteScriptAsync("$app.addGameLogEvent", logLine);
|
||||||
|
}
|
||||||
m_LogList.Add(item);
|
m_LogList.Add(item);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -244,7 +274,7 @@ namespace VRCX
|
|||||||
dt = DateTime.UtcNow;
|
dt = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $"{dt:yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'}";
|
return $"{dt:yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ParseLogLocation(FileInfo fileInfo, LogContext logContext, string line, int offset)
|
private bool ParseLogLocation(FileInfo fileInfo, LogContext logContext, string line, int offset)
|
||||||
@@ -284,6 +314,29 @@ namespace VRCX
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool ParseLogLocationDestination(FileInfo fileInfo, LogContext logContext, string line, int offset)
|
||||||
|
{
|
||||||
|
// 2021.09.02 00:02:12 Log - [Behaviour] Destination set: wrld_4432ea9b-729c-46e3-8eaf-846aa0a37fdd:15609~private(usr_032383a7-748c-4fb2-94e4-bcb928e5de6b)~nonce(72CC87D420C1D49AEFFBEE8824C84B2DF0E38678E840661E)
|
||||||
|
// 2021.09.02 00:49:15 Log - [Behaviour] Destination fetching: wrld_4432ea9b-729c-46e3-8eaf-846aa0a37fdd
|
||||||
|
|
||||||
|
if (string.Compare(line, offset, "[Behaviour] Destination fetching: ", 0, 34, StringComparison.Ordinal) == 0)
|
||||||
|
{
|
||||||
|
var location = line.Substring(offset + 34);
|
||||||
|
|
||||||
|
AppendLog(new[]
|
||||||
|
{
|
||||||
|
fileInfo.Name,
|
||||||
|
ConvertLogTimeToISO8601(line),
|
||||||
|
"location-destination",
|
||||||
|
location
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private bool ParseLogOnPlayerJoinedOrLeft(FileInfo fileInfo, LogContext logContext, string line, int offset)
|
private bool ParseLogOnPlayerJoinedOrLeft(FileInfo fileInfo, LogContext logContext, string line, int offset)
|
||||||
{
|
{
|
||||||
// 2020.10.31 23:36:58 Log - [NetworkManager] OnPlayerJoined pypy
|
// 2020.10.31 23:36:58 Log - [NetworkManager] OnPlayerJoined pypy
|
||||||
@@ -515,6 +568,28 @@ namespace VRCX
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool ParseLogWorldVRCX(FileInfo fileInfo, LogContext logContext, string line, int offset)
|
||||||
|
{
|
||||||
|
// [VRCX] VideoPlay(PyPyDance) "https://jd.pypy.moe/api/v1/videos/-Q3pdlsQxOk.mp4",0.5338666,260.6938,"1339 : Le Freak (Random)"
|
||||||
|
|
||||||
|
if (string.Compare(line, offset, "[VRCX] ", 0, 7, StringComparison.Ordinal) == 0)
|
||||||
|
{
|
||||||
|
var data = line.Substring(offset + 7);
|
||||||
|
|
||||||
|
AppendLog(new[]
|
||||||
|
{
|
||||||
|
fileInfo.Name,
|
||||||
|
ConvertLogTimeToISO8601(line),
|
||||||
|
"vrcx",
|
||||||
|
data
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private bool ParseLogSDK2VideoPlay(FileInfo fileInfo, LogContext logContext, string line, int offset)
|
private bool ParseLogSDK2VideoPlay(FileInfo fileInfo, LogContext logContext, string line, int offset)
|
||||||
{
|
{
|
||||||
// 2021.04.23 13:12:25 Log - User Natsumi-sama added URL https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
// 2021.04.23 13:12:25 Log - User Natsumi-sama added URL https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
||||||
@@ -579,14 +654,10 @@ namespace VRCX
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
m_ResetLog = true;
|
|
||||||
m_Thread?.Interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string[][] Get()
|
public string[][] Get()
|
||||||
{
|
{
|
||||||
|
Update();
|
||||||
|
|
||||||
if (m_ResetLog == false &&
|
if (m_ResetLog == false &&
|
||||||
m_LogList.Count > 0)
|
m_LogList.Count > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ namespace VRCX
|
|||||||
private Device _device;
|
private Device _device;
|
||||||
private Texture2D _texture1;
|
private Texture2D _texture1;
|
||||||
private Texture2D _texture2;
|
private Texture2D _texture2;
|
||||||
private OffScreenBrowser _browser1;
|
public static OffScreenBrowser _browser1;
|
||||||
private OffScreenBrowser _browser2;
|
public static OffScreenBrowser _browser2;
|
||||||
private bool _active;
|
private bool _active;
|
||||||
|
|
||||||
static VRCXVR()
|
static VRCXVR()
|
||||||
|
|||||||
@@ -147,6 +147,10 @@ namespace VRCX
|
|||||||
{
|
{
|
||||||
request.UserAgent = value;
|
request.UserAgent = value;
|
||||||
}
|
}
|
||||||
|
else if (string.Compare(key, "Referer", StringComparison.OrdinalIgnoreCase) == 0)
|
||||||
|
{
|
||||||
|
request.Referer = value;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
request.Headers.Add(key, value);
|
request.Headers.Add(key, value);
|
||||||
|
|||||||
+1581
-682
File diff suppressed because it is too large
Load Diff
+121
-54
@@ -173,6 +173,7 @@ html
|
|||||||
span(v-else-if="scope.row.status === 'busy'") Do Not Disturb
|
span(v-else-if="scope.row.status === 'busy'") Do Not Disturb
|
||||||
span(v-else) Offline
|
span(v-else) Offline
|
||||||
i.x-user-status(:class="statusClass(scope.row.status)")
|
i.x-user-status(:class="statusClass(scope.row.status)")
|
||||||
|
span
|
||||||
span(v-text="scope.row.statusDescription")
|
span(v-text="scope.row.statusDescription")
|
||||||
template(v-else-if="scope.row.type === 'Avatar'")
|
template(v-else-if="scope.row.type === 'Avatar'")
|
||||||
avatar-info(:imageurl="scope.row.currentAvatarImageUrl" :userid="scope.row.userId" :hintownerid="scope.row.ownerId" :hintavatarname="scope.row.avatarName")
|
avatar-info(:imageurl="scope.row.currentAvatarImageUrl" :userid="scope.row.userId" :hintownerid="scope.row.ownerId" :hintavatarname="scope.row.avatarName")
|
||||||
@@ -183,10 +184,10 @@ html
|
|||||||
template(#tool)
|
template(#tool)
|
||||||
div(style="margin:0 0 10px;display:flex;align-items:center")
|
div(style="margin:0 0 10px;display:flex;align-items:center")
|
||||||
el-select(v-model="gameLogTable.filters[0].value" @change="saveTableFilters" multiple clearable collapse-tags style="flex:1" placeholder="Filter")
|
el-select(v-model="gameLogTable.filters[0].value" @change="saveTableFilters" multiple clearable collapse-tags style="flex:1" placeholder="Filter")
|
||||||
el-option(v-once v-for="type in ['Location', 'OnPlayerJoined', 'OnPlayerLeft', 'PortalSpawn', 'Event', 'VideoPlay']" :key="type" :label="type" :value="type")
|
el-option(v-once v-for="type in ['Location', 'OnPlayerJoined', 'OnPlayerLeft', 'PortalSpawn', 'AvatarChange', 'Event', 'VideoPlay']" :key="type" :label="type" :value="type")
|
||||||
el-input(v-model="gameLogTable.filters[1].value" placeholder="Search" style="flex:none;width:150px;margin:0 10px")
|
el-input(v-model="gameLogTable.filters[1].value" placeholder="Search" style="flex:none;width:150px;margin:0 10px")
|
||||||
el-tooltip(placement="bottom" content="Reset game log" :disabled="hideTooltips")
|
el-tooltip(placement="bottom" content="Reload game log" :disabled="hideTooltips")
|
||||||
el-button(type="default" @click="resetGameLog()" icon="el-icon-refresh" circle style="flex:none")
|
el-button(type="default" @click="refreshEntireGameLog" icon="el-icon-refresh" circle style="flex:none")
|
||||||
el-table-column(label="Date" prop="created_at" sortable="custom" width="90")
|
el-table-column(label="Date" prop="created_at" sortable="custom" width="90")
|
||||||
template(v-once #default="scope")
|
template(v-once #default="scope")
|
||||||
el-tooltip(placement="right")
|
el-tooltip(placement="right")
|
||||||
@@ -194,17 +195,28 @@ html
|
|||||||
span {{ scope.row.created_at | formatDate('YYYY-MM-DD HH24:MI:SS') }}
|
span {{ scope.row.created_at | formatDate('YYYY-MM-DD HH24:MI:SS') }}
|
||||||
span {{ scope.row.created_at | formatDate('MM-DD HH24:MI') }}
|
span {{ scope.row.created_at | formatDate('MM-DD HH24:MI') }}
|
||||||
el-table-column(label="Type" prop="type" width="120")
|
el-table-column(label="Type" prop="type" width="120")
|
||||||
|
template(v-once #default="scope")
|
||||||
|
span.x-link(v-if="scope.row.location && scope.row.type !== 'Location'" v-text="scope.row.type" @click="showWorldDialog(scope.row.location)")
|
||||||
|
span(v-else v-text="scope.row.type")
|
||||||
|
el-table-column(label="User" prop="displayName" width="160")
|
||||||
|
template(v-once #default="scope")
|
||||||
|
span.x-link(v-text="scope.row.displayName" @click="lookupUser(scope.row)")
|
||||||
el-table-column(label="Detail" prop="data")
|
el-table-column(label="Detail" prop="data")
|
||||||
template(v-once #default="scope")
|
template(v-once #default="scope")
|
||||||
location(v-if="scope.row.type === 'Location'" :location="scope.row.data[0]" :hint="scope.row.data[1]")
|
location(v-if="scope.row.type === 'Location'" :location="scope.row.location" :hint="scope.row.worldName")
|
||||||
|
location(v-else-if="scope.row.type === 'PortalSpawn'" :location="scope.row.instanceId" :hint="scope.row.worldName")
|
||||||
|
template(v-else-if="scope.row.type === 'AvatarChange'")
|
||||||
|
span.x-link(@click="showUserDialog(scope.row.authorId)" v-text="scope.row.name")
|
||||||
|
template(v-if="scope.row.description && scope.row.name !== scope.row.description")
|
||||||
|
| - {{ scope.row.description }}
|
||||||
template(v-else-if="scope.row.type === 'Event'")
|
template(v-else-if="scope.row.type === 'Event'")
|
||||||
span(v-text="scope.row.data")
|
span(v-text="scope.row.data")
|
||||||
template(v-else-if="scope.row.type === 'VideoPlay'")
|
template(v-else-if="scope.row.type === 'VideoPlay'")
|
||||||
span.x-link(v-text="scope.row.data" @click="openExternalLink(scope.row.data)")
|
span(v-if="scope.row.videoId") {{ scope.row.videoId }}:
|
||||||
template(v-if="scope.row.displayName")
|
span.x-link(v-if="scope.row.videoName" @click="openExternalLink(scope.row.videoUrl)" v-text="scope.row.videoName")
|
||||||
span.x-link(@click="lookupUser(scope.row.displayName)") ({{ scope.row.displayName }})
|
span.x-link(v-else @click="openExternalLink(scope.row.videoUrl)" v-text="scope.row.videoUrl")
|
||||||
template(v-else-if="scope.row.type === 'Notification'")
|
template(v-else-if="scope.row.type === 'Notification' || scope.row.type === 'OnPlayerJoined' || scope.row.type === 'OnPlayerLeft'")
|
||||||
span.x-link(v-else v-text="scope.row.data" @click="lookupUser(scope.row.data)")
|
span.x-link(v-else v-text="scope.row.data")
|
||||||
|
|
||||||
//- search
|
//- search
|
||||||
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'search'")
|
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'search'")
|
||||||
@@ -458,15 +470,26 @@ html
|
|||||||
span(v-else-if='scope.row.details && scope.row.details.inviteMessage' v-text="scope.row.details.inviteMessage")
|
span(v-else-if='scope.row.details && scope.row.details.inviteMessage' v-text="scope.row.details.inviteMessage")
|
||||||
span(v-else-if='scope.row.details && scope.row.details.requestMessage' v-text="scope.row.details.requestMessage")
|
span(v-else-if='scope.row.details && scope.row.details.requestMessage' v-text="scope.row.details.requestMessage")
|
||||||
span(v-else-if='scope.row.details && scope.row.details.responseMessage' v-text="scope.row.details.responseMessage")
|
span(v-else-if='scope.row.details && scope.row.details.responseMessage' v-text="scope.row.details.responseMessage")
|
||||||
el-table-column(label="Action" width="80" align="right")
|
el-table-column(label="Action" width="100" align="right")
|
||||||
template(v-once #default="scope")
|
template(v-once #default="scope")
|
||||||
template(v-if="scope.row.senderUserId !== API.currentUser.id")
|
template(v-if="scope.row.senderUserId !== API.currentUser.id && !scope.row.$isExpired")
|
||||||
el-button(v-if="scope.row.type === 'friendRequest'" type="text" icon="el-icon-check" size="mini" @click="acceptNotification(scope.row)")
|
template(v-if="scope.row.type === 'friendRequest'")
|
||||||
el-button(v-else-if="scope.row.type === 'invite'" type="text" icon="el-icon-chat-line-square" size="mini" @click="showSendInviteResponseDialog(scope.row)")
|
el-tooltip(placement="top" content="Accept" :disabled="hideTooltips")
|
||||||
|
el-button(type="text" icon="el-icon-check" size="mini" @click="acceptNotification(scope.row)")
|
||||||
|
template(v-else-if="scope.row.type === 'invite'")
|
||||||
|
el-tooltip(placement="top" content="Decline with message" :disabled="hideTooltips")
|
||||||
|
el-button(type="text" icon="el-icon-chat-line-square" size="mini" @click="showSendInviteResponseDialog(scope.row)")
|
||||||
template(v-else-if="scope.row.type === 'requestInvite'")
|
template(v-else-if="scope.row.type === 'requestInvite'")
|
||||||
el-button(v-if="lastLocation.location && isGameRunning && !checkCanInvite(lastLocation.location)" type="text" icon="el-icon-check" size="mini" @click="acceptRequestInvite(scope.row)")
|
template(v-if="lastLocation.location && isGameRunning && !checkCanInvite(lastLocation.location)")
|
||||||
|
el-tooltip(placement="top" content="Invite" :disabled="hideTooltips")
|
||||||
|
el-button(type="text" icon="el-icon-check" size="mini" @click="acceptRequestInvite(scope.row)")
|
||||||
|
el-tooltip(placement="top" content="Decline with message" :disabled="hideTooltips")
|
||||||
el-button(type="text" icon="el-icon-chat-line-square" size="mini" style="margin-left:5px" @click="showSendInviteRequestResponseDialog(scope.row)")
|
el-button(type="text" icon="el-icon-chat-line-square" size="mini" style="margin-left:5px" @click="showSendInviteRequestResponseDialog(scope.row)")
|
||||||
|
template(v-if="scope.row.type !== 'requestInviteResponse' && scope.row.type !== 'inviteResponse' && scope.row.type !== 'message'")
|
||||||
|
el-tooltip(placement="top" content="Decline" :disabled="hideTooltips")
|
||||||
el-button(type="text" icon="el-icon-close" size="mini" style="margin-left:5px" @click="hideNotification(scope.row)")
|
el-button(type="text" icon="el-icon-close" size="mini" style="margin-left:5px" @click="hideNotification(scope.row)")
|
||||||
|
el-tooltip(placement="top" content="Delete log" :disabled="hideTooltips")
|
||||||
|
el-button(type="text" icon="el-icon-delete" size="mini" style="margin-left:5px" @click="deleteNotificationLog(scope.row)")
|
||||||
|
|
||||||
//- profile
|
//- profile
|
||||||
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'profile'")
|
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'profile'")
|
||||||
@@ -696,10 +719,10 @@ html
|
|||||||
el-radio-button(label="dark") Dark
|
el-radio-button(label="dark") Dark
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name VRCPlus Profile Icons
|
span.name VRCPlus Profile Icons
|
||||||
el-switch(v-model="displayVRCPlusIconsAsAvatar")
|
el-switch(v-model="displayVRCPlusIconsAsAvatar" @change="saveOpenVROption")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Disable Tooltips
|
span.name Disable Tooltips
|
||||||
el-switch(v-model="hideTooltips")
|
el-switch(v-model="hideTooltips" @change="saveOpenVROption")
|
||||||
div.options-container
|
div.options-container
|
||||||
span.header Side Panel
|
span.header Side Panel
|
||||||
br
|
br
|
||||||
@@ -766,10 +789,16 @@ html
|
|||||||
span * Only works when VRChat is running.
|
span * Only works when VRChat is running.
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Enable
|
span.name Enable
|
||||||
el-switch(v-model="discordActive")
|
el-switch(v-model="discordActive" @change="saveDiscordOption")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Instance details
|
span.name Instance type/player count
|
||||||
el-switch(v-model="discordInstance" :disabled="!discordActive")
|
el-switch(v-model="discordInstance" @change="saveDiscordOption" :disabled="!discordActive")
|
||||||
|
div.options-container-item
|
||||||
|
span.name Join button (public only)
|
||||||
|
el-switch(v-model="discordJoinButton" @change="saveDiscordOption" :disabled="!discordActive")
|
||||||
|
div.options-container-item
|
||||||
|
span.name Hide world details in private
|
||||||
|
el-switch(v-model="discordHideInvite" @change="saveDiscordOption" :disabled="!discordActive")
|
||||||
div.options-container
|
div.options-container
|
||||||
span.header SteamVR Overlay
|
span.header SteamVR Overlay
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
@@ -782,61 +811,64 @@ html
|
|||||||
br
|
br
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Enable
|
span.name Enable
|
||||||
el-switch(v-model="openVR")
|
el-switch(v-model="openVR" @change="saveOpenVROption")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Force Run (Opens SteamVR)
|
span.name Force Run (Opens SteamVR)
|
||||||
el-switch(v-model="openVRAlways" :disabled="!openVR")
|
el-switch(v-model="openVRAlways" @change="saveOpenVROption" :disabled="!openVR")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Hide Private Worlds
|
span.name Hide Private Worlds
|
||||||
el-switch(v-model="hidePrivateFromFeed")
|
el-switch(v-model="hidePrivateFromFeed" @change="saveOpenVROption")
|
||||||
br
|
br
|
||||||
span.sub-header Wrist Feed
|
span.sub-header Wrist Feed
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Wrist Feed Overlay
|
span.name Wrist Feed Overlay
|
||||||
el-switch(v-model="overlayWrist" :disabled="!openVR")
|
el-switch(v-model="overlayWrist" @change="saveOpenVROption" :disabled="!openVR")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name(style="min-width:137px") Overlay Button
|
span.name(style="min-width:137px") Overlay Button
|
||||||
el-switch(v-model="overlaybutton" inactive-text="Grip" active-text="Menu" :disabled="!openVR || !overlayWrist")
|
el-switch(v-model="overlaybutton" @change="saveOpenVROption" inactive-text="Grip" active-text="Menu" :disabled="!openVR || !overlayWrist")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Background Color
|
span.name Background Color
|
||||||
el-switch(v-model="vrBackgroundEnabled" :disabled="!openVR || !overlayWrist")
|
el-switch(v-model="vrBackgroundEnabled" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Minimal Feed Icons
|
span.name Minimal Feed Icons
|
||||||
el-switch(v-model="minimalFeed" :disabled="!openVR || !overlayWrist")
|
el-switch(v-model="minimalFeed" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Hide VR Devices
|
span.name Hide VR Devices
|
||||||
el-switch(v-model="hideDevicesFromFeed" :disabled="!openVR || !overlayWrist")
|
el-switch(v-model="hideDevicesFromFeed" @change="saveOpenVROption" :disabled="!openVR || !overlayWrist")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
el-button(size="small" icon="el-icon-notebook-2" @click="showWristFeedFiltersDialog()" :disabled="!openVR || !overlayWrist") Wrist Feed Filters
|
el-button(size="small" icon="el-icon-notebook-2" @click="showWristFeedFiltersDialog" :disabled="!openVR || !overlayWrist") Wrist Feed Filters
|
||||||
br
|
br
|
||||||
span.sub-header Notifications
|
span.sub-header Notifications
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Overlay Notifications
|
span.name Overlay Notifications
|
||||||
el-switch(v-model="overlayNotifications" :disabled="!openVR")
|
el-switch(v-model="overlayNotifications" @change="saveOpenVROption" :disabled="!openVR")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
el-button(size="small" icon="el-icon-rank" @click="showNotificationPositionDialog()" :disabled="!overlayNotifications || !openVR") Notification Position
|
el-button(size="small" icon="el-icon-rank" @click="showNotificationPositionDialog" :disabled="!overlayNotifications || !openVR") Notification Position
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name XSOverlay Notifications
|
span.name XSOverlay Notifications
|
||||||
el-switch(v-model="xsNotifications")
|
el-switch(v-model="xsNotifications" @change="saveOpenVROption")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
el-button(size="small" icon="el-icon-time" @click="promptNotificationTimeout()" :disabled="(!overlayNotifications || !openVR) && !xsNotifications") Notification Timeout
|
span.name User images (slower)
|
||||||
|
el-switch(v-model="imageNotifications" @change="saveOpenVROption")
|
||||||
|
div.options-container-item
|
||||||
|
el-button(size="small" icon="el-icon-time" @click="promptNotificationTimeout" :disabled="(!overlayNotifications || !openVR) && !xsNotifications") Notification Timeout
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Desktop Notifications, When to display:
|
span.name Desktop Notifications, When to display:
|
||||||
br
|
br
|
||||||
el-radio-group(v-model="desktopToast" size="mini")
|
el-radio-group(v-model="desktopToast" @change="saveOpenVROption" size="mini")
|
||||||
el-radio-button(label="Never")
|
el-radio-button(label="Never")
|
||||||
el-radio-button(label="Inside VR")
|
el-radio-button(label="Inside VR")
|
||||||
el-radio-button(label="Game Closed")
|
el-radio-button(label="Game Closed")
|
||||||
el-radio-button(label="Game Running")
|
el-radio-button(label="Game Running")
|
||||||
el-radio-button(label="Always")
|
el-radio-button(label="Always")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
el-button(size="small" icon="el-icon-chat-square" @click="showNotyFeedFiltersDialog()") Notification Filters
|
el-button(size="small" icon="el-icon-chat-square" @click="showNotyFeedFiltersDialog") Notification Filters
|
||||||
br
|
br
|
||||||
span.sub-header Text-To-Speech Options
|
span.sub-header Text-To-Speech Options
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Notification TTS, When to play:
|
span.name Notification TTS, When to play:
|
||||||
br
|
br
|
||||||
el-radio-group(v-model="notificationTTS" size="mini")
|
el-radio-group(v-model="notificationTTS" @change="saveNotificationTTS" size="mini")
|
||||||
el-radio-button(label="Never")
|
el-radio-button(label="Never")
|
||||||
el-radio-button(label="Inside VR")
|
el-radio-button(label="Inside VR")
|
||||||
el-radio-button(label="Game Closed")
|
el-radio-button(label="Game Closed")
|
||||||
@@ -857,31 +889,30 @@ html
|
|||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Download on invite:
|
span.name Download on invite:
|
||||||
br
|
br
|
||||||
el-radio-group(v-model="worldAutoCacheInvite" size="mini")
|
el-radio-group(v-model="worldAutoCacheInvite" @change="saveOpenVROption" size="mini")
|
||||||
el-radio-button(label="Never")
|
el-radio-button(label="Never")
|
||||||
el-radio-button(label="Game Closed")
|
el-radio-button(label="Game Closed")
|
||||||
el-radio-button(label="Game Running")
|
el-radio-button(label="Game Running")
|
||||||
el-radio-button(label="Always")
|
el-radio-button(label="Always")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
el-switch(v-model="worldAutoCacheInviteFilter" inactive-text="VIP" active-text="Everyone" :disabled="worldAutoCacheInvite == 'Never'")
|
el-switch(v-model="worldAutoCacheInviteFilter" @change="saveOpenVROption" inactive-text="VIP" active-text="Everyone" :disabled="worldAutoCacheInvite === 'Never'")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name Download on GPS:
|
span.name Download on GPS:
|
||||||
br
|
br
|
||||||
el-radio-group(v-model="worldAutoCacheGPS" size="mini")
|
el-radio-group(v-model="worldAutoCacheGPS" @change="saveOpenVROption" size="mini")
|
||||||
el-radio-button(label="Never")
|
el-radio-button(label="Never")
|
||||||
el-radio-button(label="Game Closed")
|
el-radio-button(label="Game Closed")
|
||||||
el-radio-button(label="Game Running")
|
el-radio-button(label="Game Running")
|
||||||
el-radio-button(label="Always")
|
el-radio-button(label="Always")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
el-switch(v-model="worldAutoCacheGPSFilter" inactive-text="VIP" active-text="Everyone" :disabled="worldAutoCacheGPS == 'Never'")
|
el-switch(v-model="worldAutoCacheGPSFilter" @change="saveOpenVROption" inactive-text="VIP" active-text="Everyone" :disabled="worldAutoCacheGPS === 'Never'")
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
el-button-group
|
el-button(size="small" icon="el-icon-download" @click="showDownloadDialog") Download History
|
||||||
el-button(size="small" icon="el-icon-download" @click="showDownloadDialog()") Download History
|
|
||||||
br
|
br
|
||||||
span.sub-header Automatically Manage Cache When Closing VRChat
|
span.sub-header Automatically Manage Cache When Closing VRChat
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
span.name(style="min-width:300px") Auto delete old versions from cache
|
span.name(style="min-width:300px") Auto delete old versions from cache
|
||||||
el-switch(v-model="autoSweepVRChatCache")
|
el-switch(v-model="autoSweepVRChatCache" @change="saveOpenVROption")
|
||||||
div.options-container
|
div.options-container
|
||||||
span.header Application
|
span.header Application
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
@@ -900,6 +931,13 @@ html
|
|||||||
el-button-group
|
el-button-group
|
||||||
el-button(size="small" icon="el-icon-s-operation" @click="showLaunchOptions()") Launch Options
|
el-button(size="small" icon="el-icon-s-operation" @click="showLaunchOptions()") Launch Options
|
||||||
el-button(size="small" icon="el-icon-s-operation" @click="showVRChatConfig()") VRChat config.json
|
el-button(size="small" icon="el-icon-s-operation" @click="showVRChatConfig()") VRChat config.json
|
||||||
|
div.options-container
|
||||||
|
span.header YouTube API
|
||||||
|
div.options-container-item
|
||||||
|
span.name Enabled
|
||||||
|
el-switch(v-model="youTubeApi" @change="changeYouTubeApi")
|
||||||
|
div.options-container-item
|
||||||
|
el-button(size="small" icon="el-icon-caret-right" @click="showYouTubeApiDialog") YouTube API Key
|
||||||
div.options-container(style="margin-top:45px;border-top:1px solid #eee;padding-top:30px")
|
div.options-container(style="margin-top:45px;border-top:1px solid #eee;padding-top:30px")
|
||||||
span.header Legal Notice
|
span.header Legal Notice
|
||||||
div.options-container-item
|
div.options-container-item
|
||||||
@@ -1053,6 +1091,7 @@ html
|
|||||||
el-button(:type="(userDialog.incomingRequest || userDialog.outgoingRequest) ? 'success' : (userDialog.isBlock || userDialog.isMute || userDialog.isHideAvatar) ? 'danger' : 'default'" icon="el-icon-more" circle style="margin-left:5px")
|
el-button(:type="(userDialog.incomingRequest || userDialog.outgoingRequest) ? 'success' : (userDialog.isBlock || userDialog.isMute || userDialog.isHideAvatar) ? 'danger' : 'default'" icon="el-icon-more" circle style="margin-left:5px")
|
||||||
el-dropdown-menu(#default="dropdown")
|
el-dropdown-menu(#default="dropdown")
|
||||||
el-dropdown-item(icon="el-icon-refresh" command="Refresh") Refresh
|
el-dropdown-item(icon="el-icon-refresh" command="Refresh") Refresh
|
||||||
|
el-dropdown-item(icon="el-icon-s-order" command="Copy User") Copy User URL
|
||||||
template(v-if="userDialog.ref.id === API.currentUser.id")
|
template(v-if="userDialog.ref.id === API.currentUser.id")
|
||||||
el-dropdown-item(icon="el-icon-picture-outline" command="Manage Gallery" divided) Manage Gallery/Icons
|
el-dropdown-item(icon="el-icon-picture-outline" command="Manage Gallery" divided) Manage Gallery/Icons
|
||||||
el-dropdown-item(icon="el-icon-s-custom" command="Show Avatar Author") Show Avatar Author
|
el-dropdown-item(icon="el-icon-s-custom" command="Show Avatar Author") Show Avatar Author
|
||||||
@@ -1075,7 +1114,7 @@ html
|
|||||||
el-dropdown-item(v-else icon="el-icon-plus" command="Send Friend Request") Send Friend Request
|
el-dropdown-item(v-else icon="el-icon-plus" command="Send Friend Request") Send Friend Request
|
||||||
el-dropdown-item(icon="el-icon-s-custom" command="Show Avatar Author" divided) Show Avatar Author
|
el-dropdown-item(icon="el-icon-s-custom" command="Show Avatar Author" divided) Show Avatar Author
|
||||||
el-dropdown-item(icon="el-icon-s-custom" command="Show Fallback Avatar Details") Show Fallback Avatar Details
|
el-dropdown-item(icon="el-icon-s-custom" command="Show Fallback Avatar Details") Show Fallback Avatar Details
|
||||||
el-dropdown-item(v-if="userDialog.currentAvatarImageUrl !== 'https://assets.vrchat.com/system/defaultAvatar.png'" icon="el-icon-picture-outline" command="Previous Images") Show Avatar Previous Images
|
el-dropdown-item(v-if="userDialog.ref.currentAvatarImageUrl !== 'https://assets.vrchat.com/system/defaultAvatar.png'" icon="el-icon-picture-outline" command="Previous Images") Show Avatar Previous Images
|
||||||
el-dropdown-item(v-if="userDialog.isBlock" icon="el-icon-circle-check" command="Unblock" divided style="color:#F56C6C") Unblock
|
el-dropdown-item(v-if="userDialog.isBlock" icon="el-icon-circle-check" command="Unblock" divided style="color:#F56C6C") Unblock
|
||||||
el-dropdown-item(v-else icon="el-icon-circle-close" command="Block" divided :disabled="userDialog.ref.$isModerator") Block
|
el-dropdown-item(v-else icon="el-icon-circle-close" command="Block" divided :disabled="userDialog.ref.$isModerator") Block
|
||||||
el-dropdown-item(v-if="userDialog.isMute" icon="el-icon-microphone" command="Unmute" style="color:#F56C6C") Unmute
|
el-dropdown-item(v-if="userDialog.isMute" icon="el-icon-microphone" command="Unmute" style="color:#F56C6C") Unmute
|
||||||
@@ -1665,6 +1704,16 @@ html
|
|||||||
el-button(size="small" @click="VRChatConfigDialog.visible = false") Cancel
|
el-button(size="small" @click="VRChatConfigDialog.visible = false") Cancel
|
||||||
el-button(type="primary" size="small" :disabled="VRChatConfigDialog.loading" @click="saveVRChatConfigFile") Save
|
el-button(type="primary" size="small" :disabled="VRChatConfigDialog.loading" @click="saveVRChatConfigFile") Save
|
||||||
|
|
||||||
|
//- dialog: YouTube Api Dialog
|
||||||
|
el-dialog.x-dialog(ref="youTubeApiDialog" :visible.sync="youTubeApiDialog.visible" title="YouTube API" width="400px")
|
||||||
|
div(style='font-size:12px;')
|
||||||
|
| Enter your YouTube API Key (optional) #[br]
|
||||||
|
el-input(type="textarea" v-model="youTubeApiKey" placeholder="YouTube API Key" maxlength="39" show-word-limit style="dispaly:block;margin-top:10px")
|
||||||
|
template(#footer)
|
||||||
|
div(style="display:flex")
|
||||||
|
el-button(size="small" @click="openExternalLink('https://rapidapi.com/blog/how-to-get-youtube-api-key/')") Guide
|
||||||
|
el-button(type="primary" size="small" @click="testYouTubeApiKey" style="margin-left:auto") Save
|
||||||
|
|
||||||
//- dialog: Cache Download
|
//- dialog: Cache Download
|
||||||
el-dialog.x-dialog(ref="downloadDialog" :visible.sync="downloadDialog.visible" title="Download History" width="770px")
|
el-dialog.x-dialog(ref="downloadDialog" :visible.sync="downloadDialog.visible" title="Download History" width="770px")
|
||||||
div(v-if="downloadInProgress && downloadCurrent.ref")
|
div(v-if="downloadInProgress && downloadCurrent.ref")
|
||||||
@@ -1769,7 +1818,7 @@ html
|
|||||||
el-button(type="primary" size="small" style="margin-left:auto" @click="notificationPositionDialog.visible = false") OK
|
el-button(type="primary" size="small" style="margin-left:auto" @click="notificationPositionDialog.visible = false") OK
|
||||||
|
|
||||||
//- dialog: Noty feed filters
|
//- dialog: Noty feed filters
|
||||||
el-dialog.x-dialog(ref="notyFeedFiltersDialog" :visible.sync="notyFeedFiltersDialog.visible" title="Notification Filters" width="480px")
|
el-dialog.x-dialog(ref="notyFeedFiltersDialog" :visible.sync="notyFeedFiltersDialog.visible" title="Notification Filters" width="500px")
|
||||||
.toggle-list
|
.toggle-list
|
||||||
.toggle-item
|
.toggle-item
|
||||||
span.toggle-name OnPlayerJoining
|
span.toggle-name OnPlayerJoining
|
||||||
@@ -1868,21 +1917,30 @@ html
|
|||||||
el-radio-button(label="Friends")
|
el-radio-button(label="Friends")
|
||||||
.toggle-item
|
.toggle-item
|
||||||
span.toggle-name Portal Spawn
|
span.toggle-name Portal Spawn
|
||||||
|
el-tooltip(placement="top" style="margin-left:5px" content="Requires '--enable-sdk-log-levels' steam launch option")
|
||||||
|
i.el-icon-warning
|
||||||
el-radio-group(v-model="sharedFeedFilters.noty.PortalSpawn" size="mini")
|
el-radio-group(v-model="sharedFeedFilters.noty.PortalSpawn" size="mini")
|
||||||
el-radio-button(label="Off")
|
el-radio-button(label="Off")
|
||||||
el-radio-button(label="VIP")
|
el-radio-button(label="VIP")
|
||||||
el-radio-button(label="Friends")
|
el-radio-button(label="Friends")
|
||||||
el-radio-button(label="Everyone")
|
el-radio-button(label="Everyone")
|
||||||
.toggle-item
|
//- .toggle-item
|
||||||
span.toggle-name Events
|
//- span.toggle-name Avatar Change
|
||||||
el-radio-group(v-model="sharedFeedFilters.noty.Event" size="mini")
|
//- el-radio-group(v-model="sharedFeedFilters.noty.AvatarChange" size="mini")
|
||||||
el-radio-button(label="Off")
|
//- el-radio-button(label="Off")
|
||||||
el-radio-button(label="On")
|
//- el-radio-button(label="VIP")
|
||||||
|
//- el-radio-button(label="Friends")
|
||||||
|
//- el-radio-button(label="Everyone")
|
||||||
.toggle-item
|
.toggle-item
|
||||||
span.toggle-name Video Play
|
span.toggle-name Video Play
|
||||||
el-radio-group(v-model="sharedFeedFilters.noty.VideoPlay" size="mini")
|
el-radio-group(v-model="sharedFeedFilters.noty.VideoPlay" size="mini")
|
||||||
el-radio-button(label="Off")
|
el-radio-button(label="Off")
|
||||||
el-radio-button(label="On")
|
el-radio-button(label="On")
|
||||||
|
.toggle-item
|
||||||
|
span.toggle-name Events
|
||||||
|
el-radio-group(v-model="sharedFeedFilters.noty.Event" size="mini")
|
||||||
|
el-radio-button(label="Off")
|
||||||
|
el-radio-button(label="On")
|
||||||
.toggle-item
|
.toggle-item
|
||||||
span.toggle-name Blocked Player Joins
|
span.toggle-name Blocked Player Joins
|
||||||
el-radio-group(v-model="sharedFeedFilters.noty.BlockedOnPlayerJoined" size="mini")
|
el-radio-group(v-model="sharedFeedFilters.noty.BlockedOnPlayerJoined" size="mini")
|
||||||
@@ -1916,7 +1974,7 @@ html
|
|||||||
el-button(type="primary" size="small" style="margin-left:10px" @click="saveSharedFeedFilters") Save
|
el-button(type="primary" size="small" style="margin-left:10px" @click="saveSharedFeedFilters") Save
|
||||||
|
|
||||||
//- dialog: wrist feed filters
|
//- dialog: wrist feed filters
|
||||||
el-dialog.x-dialog(ref="wristFeedFiltersDialog" :visible.sync="wristFeedFiltersDialog.visible" title="Wrist Feed Filters" width="480px")
|
el-dialog.x-dialog(ref="wristFeedFiltersDialog" :visible.sync="wristFeedFiltersDialog.visible" title="Wrist Feed Filters" width="500px")
|
||||||
.toggle-list
|
.toggle-list
|
||||||
.toggle-item
|
.toggle-item
|
||||||
span.toggle-name Self Location
|
span.toggle-name Self Location
|
||||||
@@ -2020,19 +2078,28 @@ html
|
|||||||
el-radio-button(label="Friends")
|
el-radio-button(label="Friends")
|
||||||
.toggle-item
|
.toggle-item
|
||||||
span.toggle-name Portal Spawn
|
span.toggle-name Portal Spawn
|
||||||
|
el-tooltip(placement="top" style="margin-left:5px" content="Requires '--enable-sdk-log-levels' steam launch option")
|
||||||
|
i.el-icon-warning
|
||||||
el-radio-group(v-model="sharedFeedFilters.wrist.PortalSpawn" size="mini")
|
el-radio-group(v-model="sharedFeedFilters.wrist.PortalSpawn" size="mini")
|
||||||
el-radio-button(label="Off")
|
el-radio-button(label="Off")
|
||||||
el-radio-button(label="VIP")
|
el-radio-button(label="VIP")
|
||||||
el-radio-button(label="Friends")
|
el-radio-button(label="Friends")
|
||||||
el-radio-button(label="Everyone")
|
el-radio-button(label="Everyone")
|
||||||
|
//- .toggle-item
|
||||||
|
//- span.toggle-name Avatar Change
|
||||||
|
//- el-radio-group(v-model="sharedFeedFilters.wrist.AvatarChange" size="mini")
|
||||||
|
//- el-radio-button(label="Off")
|
||||||
|
//- el-radio-button(label="VIP")
|
||||||
|
//- el-radio-button(label="Friends")
|
||||||
|
//- el-radio-button(label="Everyone")
|
||||||
.toggle-item
|
.toggle-item
|
||||||
span.toggle-name Events
|
span.toggle-name Video Play
|
||||||
el-radio-group(v-model="sharedFeedFilters.wrist.Event" size="mini")
|
el-radio-group(v-model="sharedFeedFilters.wrist.VideoPlay" size="mini")
|
||||||
el-radio-button(label="Off")
|
el-radio-button(label="Off")
|
||||||
el-radio-button(label="On")
|
el-radio-button(label="On")
|
||||||
.toggle-item
|
.toggle-item
|
||||||
span.toggle-name Video Play
|
span.toggle-name Events
|
||||||
el-radio-group(v-model="sharedFeedFilters.noty.VideoPlay" size="mini")
|
el-radio-group(v-model="sharedFeedFilters.wrist.Event" size="mini")
|
||||||
el-radio-button(label="Off")
|
el-radio-button(label="Off")
|
||||||
el-radio-button(label="On")
|
el-radio-button(label="On")
|
||||||
.toggle-item
|
.toggle-item
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import sqliteService from '../service/sqlite.js';
|
import sqliteService from '../service/sqlite.js';
|
||||||
|
|
||||||
class Database {
|
class Database {
|
||||||
async init(userId) {
|
async initUserTables(userId) {
|
||||||
Database.userId = userId.replaceAll('-', '').replaceAll('_', '');
|
Database.userId = userId.replaceAll('-', '').replaceAll('_', '');
|
||||||
await sqliteService.executeNonQuery(
|
await sqliteService.executeNonQuery(
|
||||||
`CREATE TABLE IF NOT EXISTS ${Database.userId}_feed_gps (id INTEGER PRIMARY KEY, created_at TEXT, user_id TEXT, display_name TEXT, location TEXT, world_name TEXT, previous_location TEXT, time INTEGER)`
|
`CREATE TABLE IF NOT EXISTS ${Database.userId}_feed_gps (id INTEGER PRIMARY KEY, created_at TEXT, user_id TEXT, display_name TEXT, location TEXT, world_name TEXT, previous_location TEXT, time INTEGER)`
|
||||||
@@ -21,11 +21,32 @@ class Database {
|
|||||||
await sqliteService.executeNonQuery(
|
await sqliteService.executeNonQuery(
|
||||||
`CREATE TABLE IF NOT EXISTS ${Database.userId}_friend_log_history (id INTEGER PRIMARY KEY, created_at TEXT, type TEXT, user_id TEXT, display_name TEXT, previous_display_name TEXT, trust_level TEXT, previous_trust_level TEXT)`
|
`CREATE TABLE IF NOT EXISTS ${Database.userId}_friend_log_history (id INTEGER PRIMARY KEY, created_at TEXT, type TEXT, user_id TEXT, display_name TEXT, previous_display_name TEXT, trust_level TEXT, previous_trust_level TEXT)`
|
||||||
);
|
);
|
||||||
|
await sqliteService.executeNonQuery(
|
||||||
|
`CREATE TABLE IF NOT EXISTS ${Database.userId}_notifications (id TEXT PRIMARY KEY, created_at TEXT, type TEXT, sender_user_id TEXT, sender_username TEXT, receiver_user_id TEXT, message TEXT, world_id TEXT, world_name TEXT, image_url TEXT, invite_message TEXT, request_message TEXT, response_message TEXT, expired INTEGER)`
|
||||||
|
);
|
||||||
await sqliteService.executeNonQuery(
|
await sqliteService.executeNonQuery(
|
||||||
`CREATE TABLE IF NOT EXISTS memos (user_id TEXT PRIMARY KEY, edited_at TEXT, memo TEXT)`
|
`CREATE TABLE IF NOT EXISTS memos (user_id TEXT PRIMARY KEY, edited_at TEXT, memo TEXT)`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async initTables() {
|
||||||
|
await sqliteService.executeNonQuery(
|
||||||
|
`CREATE TABLE IF NOT EXISTS gamelog_location (id INTEGER PRIMARY KEY, created_at TEXT, location TEXT, world_id TEXT, world_name TEXT, time INTEGER, UNIQUE(created_at, location))`
|
||||||
|
);
|
||||||
|
await sqliteService.executeNonQuery(
|
||||||
|
`CREATE TABLE IF NOT EXISTS gamelog_join_leave (id INTEGER PRIMARY KEY, created_at TEXT, type TEXT, display_name TEXT, location TEXT, user_id TEXT, time INTEGER, UNIQUE(created_at, type, display_name))`
|
||||||
|
);
|
||||||
|
await sqliteService.executeNonQuery(
|
||||||
|
`CREATE TABLE IF NOT EXISTS gamelog_portal_spawn (id INTEGER PRIMARY KEY, created_at TEXT, display_name TEXT, location TEXT, user_id TEXT, instance_id TEXT, world_name TEXT, UNIQUE(created_at, display_name))`
|
||||||
|
);
|
||||||
|
await sqliteService.executeNonQuery(
|
||||||
|
`CREATE TABLE IF NOT EXISTS gamelog_video_play (id INTEGER PRIMARY KEY, created_at TEXT, video_url TEXT, video_name TEXT, video_id TEXT, location TEXT, display_name TEXT, user_id TEXT, UNIQUE(created_at, video_url))`
|
||||||
|
);
|
||||||
|
await sqliteService.executeNonQuery(
|
||||||
|
`CREATE TABLE IF NOT EXISTS gamelog_event (id INTEGER PRIMARY KEY, created_at TEXT, data TEXT, UNIQUE(created_at, data))`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async getFeedDatabase() {
|
async getFeedDatabase() {
|
||||||
var feedDatabase = [];
|
var feedDatabase = [];
|
||||||
var date = new Date();
|
var date = new Date();
|
||||||
@@ -349,6 +370,259 @@ class Database {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getGamelogDatabase() {
|
||||||
|
var gamelogDatabase = [];
|
||||||
|
var date = new Date();
|
||||||
|
date.setDate(date.getDate() - 7); // 7 day limit
|
||||||
|
var dateOffset = date.toJSON();
|
||||||
|
await sqliteService.execute((dbRow) => {
|
||||||
|
var row = {
|
||||||
|
rowId: dbRow[0],
|
||||||
|
created_at: dbRow[1],
|
||||||
|
type: 'Location',
|
||||||
|
location: dbRow[2],
|
||||||
|
worldId: dbRow[3],
|
||||||
|
worldName: dbRow[4],
|
||||||
|
time: dbRow[5]
|
||||||
|
};
|
||||||
|
gamelogDatabase.unshift(row);
|
||||||
|
}, `SELECT * FROM gamelog_location WHERE created_at >= date('${dateOffset}')`);
|
||||||
|
await sqliteService.execute((dbRow) => {
|
||||||
|
var row = {
|
||||||
|
rowId: dbRow[0],
|
||||||
|
created_at: dbRow[1],
|
||||||
|
type: dbRow[2],
|
||||||
|
displayName: dbRow[3],
|
||||||
|
location: dbRow[4],
|
||||||
|
userId: dbRow[5],
|
||||||
|
time: dbRow[6]
|
||||||
|
};
|
||||||
|
gamelogDatabase.unshift(row);
|
||||||
|
}, `SELECT * FROM gamelog_join_leave WHERE created_at >= date('${dateOffset}')`);
|
||||||
|
await sqliteService.execute((dbRow) => {
|
||||||
|
var row = {
|
||||||
|
rowId: dbRow[0],
|
||||||
|
created_at: dbRow[1],
|
||||||
|
type: 'PortalSpawn',
|
||||||
|
displayName: dbRow[2],
|
||||||
|
location: dbRow[3],
|
||||||
|
userId: dbRow[4],
|
||||||
|
instanceId: dbRow[5],
|
||||||
|
worldName: dbRow[6]
|
||||||
|
};
|
||||||
|
gamelogDatabase.unshift(row);
|
||||||
|
}, `SELECT * FROM gamelog_portal_spawn WHERE created_at >= date('${dateOffset}')`);
|
||||||
|
await sqliteService.execute((dbRow) => {
|
||||||
|
var row = {
|
||||||
|
rowId: dbRow[0],
|
||||||
|
created_at: dbRow[1],
|
||||||
|
type: 'VideoPlay',
|
||||||
|
videoUrl: dbRow[2],
|
||||||
|
videoName: dbRow[3],
|
||||||
|
videoId: dbRow[4],
|
||||||
|
location: dbRow[5],
|
||||||
|
displayName: dbRow[6],
|
||||||
|
userId: dbRow[7]
|
||||||
|
};
|
||||||
|
gamelogDatabase.unshift(row);
|
||||||
|
}, `SELECT * FROM gamelog_video_play WHERE created_at >= date('${dateOffset}')`);
|
||||||
|
await sqliteService.execute((dbRow) => {
|
||||||
|
var row = {
|
||||||
|
rowId: dbRow[0],
|
||||||
|
created_at: dbRow[1],
|
||||||
|
type: 'Event',
|
||||||
|
data: dbRow[2]
|
||||||
|
};
|
||||||
|
gamelogDatabase.unshift(row);
|
||||||
|
}, `SELECT * FROM gamelog_event WHERE created_at >= date('${dateOffset}')`);
|
||||||
|
var compareByCreatedAt = function (a, b) {
|
||||||
|
var A = a.created_at;
|
||||||
|
var B = b.created_at;
|
||||||
|
if (A < B) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (A > B) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
gamelogDatabase.sort(compareByCreatedAt);
|
||||||
|
return gamelogDatabase;
|
||||||
|
}
|
||||||
|
|
||||||
|
addGamelogLocationToDatabase(entry) {
|
||||||
|
sqliteService.executeNonQuery(
|
||||||
|
`INSERT OR IGNORE INTO gamelog_location (created_at, location, world_id, world_name, time) VALUES (@created_at, @location, @world_id, @world_name, @time)`,
|
||||||
|
{
|
||||||
|
'@created_at': entry.created_at,
|
||||||
|
'@location': entry.location,
|
||||||
|
'@world_id': entry.worldId,
|
||||||
|
'@world_name': entry.worldName,
|
||||||
|
'@time': entry.time
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateGamelogLocationTimeToDatabase(entry) {
|
||||||
|
sqliteService.executeNonQuery(
|
||||||
|
`UPDATE gamelog_location SET time = @time WHERE created_at = @created_at`,
|
||||||
|
{
|
||||||
|
'@created_at': entry.created_at,
|
||||||
|
'@time': entry.time
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
addGamelogJoinLeaveToDatabase(entry) {
|
||||||
|
sqliteService.executeNonQuery(
|
||||||
|
`INSERT OR IGNORE INTO gamelog_join_leave (created_at, type, display_name, location, user_id, time) VALUES (@created_at, @type, @display_name, @location, @user_id, @time)`,
|
||||||
|
{
|
||||||
|
'@created_at': entry.created_at,
|
||||||
|
'@type': entry.type,
|
||||||
|
'@display_name': entry.displayName,
|
||||||
|
'@location': entry.location,
|
||||||
|
'@user_id': entry.userId,
|
||||||
|
'@time': entry.time
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
addGamelogPortalSpawnToDatabase(entry) {
|
||||||
|
sqliteService.executeNonQuery(
|
||||||
|
`INSERT OR IGNORE INTO gamelog_portal_spawn (created_at, display_name, location, user_id, instance_id, world_name) VALUES (@created_at, @display_name, @location, @user_id, @instance_id, @world_name)`,
|
||||||
|
{
|
||||||
|
'@created_at': entry.created_at,
|
||||||
|
'@display_name': entry.displayName,
|
||||||
|
'@location': entry.location,
|
||||||
|
'@user_id': entry.userId,
|
||||||
|
'@instance_id': entry.instanceId,
|
||||||
|
'@world_name': entry.worldName
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
addGamelogVideoPlayToDatabase(entry) {
|
||||||
|
sqliteService.executeNonQuery(
|
||||||
|
`INSERT OR IGNORE INTO gamelog_video_play (created_at, video_url, video_name, video_id, location, display_name, user_id) VALUES (@created_at, @video_url, @video_name, @video_id, @location, @display_name, @user_id)`,
|
||||||
|
{
|
||||||
|
'@created_at': entry.created_at,
|
||||||
|
'@video_url': entry.videoUrl,
|
||||||
|
'@video_name': entry.videoName,
|
||||||
|
'@video_id': entry.videoId,
|
||||||
|
'@location': entry.location,
|
||||||
|
'@display_name': entry.displayName,
|
||||||
|
'@user_id': entry.userId
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
addGamelogEventToDatabase(entry) {
|
||||||
|
sqliteService.executeNonQuery(
|
||||||
|
`INSERT OR IGNORE INTO gamelog_event (created_at, data) VALUES (@created_at, @data)`,
|
||||||
|
{
|
||||||
|
'@created_at': entry.created_at,
|
||||||
|
'@data': entry.data
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getNotifications() {
|
||||||
|
var notifications = [];
|
||||||
|
await sqliteService.execute((dbRow) => {
|
||||||
|
var row = {
|
||||||
|
id: dbRow[0],
|
||||||
|
created_at: dbRow[1],
|
||||||
|
type: dbRow[2],
|
||||||
|
senderUserId: dbRow[3],
|
||||||
|
senderUsername: dbRow[4],
|
||||||
|
receiverUserId: dbRow[5],
|
||||||
|
message: dbRow[6],
|
||||||
|
details: {
|
||||||
|
worldId: dbRow[7],
|
||||||
|
worldName: dbRow[8],
|
||||||
|
imageUrl: dbRow[9],
|
||||||
|
inviteMessage: dbRow[10],
|
||||||
|
requestMessage: dbRow[11],
|
||||||
|
responseMessage: dbRow[12]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
row.$isExpired = false;
|
||||||
|
if (dbRow[13] === 1) {
|
||||||
|
row.$isExpired = true;
|
||||||
|
}
|
||||||
|
notifications.unshift(row);
|
||||||
|
}, `SELECT * FROM ${Database.userId}_notifications LIMIT 5000`);
|
||||||
|
return notifications;
|
||||||
|
}
|
||||||
|
|
||||||
|
addNotificationToDatabase(row) {
|
||||||
|
var entry = {
|
||||||
|
id: '',
|
||||||
|
created_at: '',
|
||||||
|
type: '',
|
||||||
|
senderUserId: '',
|
||||||
|
senderUsername: '',
|
||||||
|
receiverUserId: '',
|
||||||
|
message: '',
|
||||||
|
...row,
|
||||||
|
details: {
|
||||||
|
worldId: '',
|
||||||
|
worldName: '',
|
||||||
|
imageUrl: '',
|
||||||
|
inviteMessage: '',
|
||||||
|
requestMessage: '',
|
||||||
|
responseMessage: '',
|
||||||
|
...row.details
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var expired = 0;
|
||||||
|
if (row.$isExpired) {
|
||||||
|
expired = 1;
|
||||||
|
}
|
||||||
|
sqliteService.executeNonQuery(
|
||||||
|
`INSERT OR IGNORE INTO ${Database.userId}_notifications (id, created_at, type, sender_user_id, sender_username, receiver_user_id, message, world_id, world_name, image_url, invite_message, request_message, response_message, expired) VALUES (@id, @created_at, @type, @sender_user_id, @sender_username, @receiver_user_id, @message, @world_id, @world_name, @image_url, @invite_message, @request_message, @response_message, @expired)`,
|
||||||
|
{
|
||||||
|
'@id': entry.id,
|
||||||
|
'@created_at': entry.created_at,
|
||||||
|
'@type': entry.type,
|
||||||
|
'@sender_user_id': entry.senderUserId,
|
||||||
|
'@sender_username': entry.senderUsername,
|
||||||
|
'@receiver_user_id': entry.receiverUserId,
|
||||||
|
'@message': entry.message,
|
||||||
|
'@world_id': entry.details.worldId,
|
||||||
|
'@world_name': entry.details.worldName,
|
||||||
|
'@image_url': entry.details.imageUrl,
|
||||||
|
'@invite_message': entry.details.inviteMessage,
|
||||||
|
'@request_message': entry.details.requestMessage,
|
||||||
|
'@response_message': entry.details.responseMessage,
|
||||||
|
'@expired': expired
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteNotification(rowId) {
|
||||||
|
sqliteService.executeNonQuery(
|
||||||
|
`DELETE FROM ${Database.userId}_notifications WHERE id = @row_id`,
|
||||||
|
{
|
||||||
|
'@row_id': rowId
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNotificationExpired(entry) {
|
||||||
|
var expired = 0;
|
||||||
|
if (entry.$isExpired) {
|
||||||
|
expired = 1;
|
||||||
|
}
|
||||||
|
sqliteService.executeNonQuery(
|
||||||
|
`UPDATE ${Database.userId}_notifications SET expired = @expired WHERE id = @id`,
|
||||||
|
{
|
||||||
|
'@id': entry.id,
|
||||||
|
'@expired': expired
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = new Database();
|
var self = new Database();
|
||||||
|
|||||||
+25
-36
@@ -1,9 +1,7 @@
|
|||||||
// requires binding of LogWatcher
|
// requires binding of LogWatcher
|
||||||
|
|
||||||
// <string, object>
|
class GameLogService {
|
||||||
var contextMap = new Map();
|
parseRawGameLog(dt, type, args) {
|
||||||
|
|
||||||
function parseRawGameLog(dt, type, args) {
|
|
||||||
var gameLog = {
|
var gameLog = {
|
||||||
dt,
|
dt,
|
||||||
type
|
type
|
||||||
@@ -15,6 +13,10 @@ function parseRawGameLog(dt, type, args) {
|
|||||||
gameLog.worldName = args[1];
|
gameLog.worldName = args[1];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'location-destination':
|
||||||
|
gameLog.location = args[0];
|
||||||
|
break;
|
||||||
|
|
||||||
case 'player-joined':
|
case 'player-joined':
|
||||||
gameLog.userDisplayName = args[0];
|
gameLog.userDisplayName = args[0];
|
||||||
gameLog.userType = args[1];
|
gameLog.userType = args[1];
|
||||||
@@ -37,10 +39,14 @@ function parseRawGameLog(dt, type, args) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'video-play':
|
case 'video-play':
|
||||||
gameLog.videoURL = args[0];
|
gameLog.videoUrl = args[0];
|
||||||
gameLog.displayName = args[1];
|
gameLog.displayName = args[1];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'vrcx':
|
||||||
|
gameLog.data = args[0];
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -48,46 +54,29 @@ function parseRawGameLog(dt, type, args) {
|
|||||||
return gameLog;
|
return gameLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
class GameLogService {
|
async getAll() {
|
||||||
async poll() {
|
|
||||||
var rawGameLogs = await LogWatcher.Get();
|
|
||||||
var gameLogs = [];
|
var gameLogs = [];
|
||||||
var now = Date.now();
|
var done = false;
|
||||||
|
while (!done) {
|
||||||
|
var rawGameLogs = await LogWatcher.Get();
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
for (var [fileName, dt, type, ...args] of rawGameLogs) {
|
for (var [fileName, dt, type, ...args] of rawGameLogs) {
|
||||||
var context = contextMap.get(fileName);
|
var gameLog = this.parseRawGameLog(dt, type, args);
|
||||||
if (typeof context === 'undefined') {
|
|
||||||
context = {
|
|
||||||
updatedAt: null,
|
|
||||||
|
|
||||||
// location
|
|
||||||
location: null
|
|
||||||
};
|
|
||||||
contextMap.set(fileName, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
var gameLog = parseRawGameLog(dt, type, args);
|
|
||||||
|
|
||||||
switch (gameLog.type) {
|
|
||||||
case 'location':
|
|
||||||
context.location = gameLog.location;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
context.updatedAt = now;
|
|
||||||
|
|
||||||
gameLogs.push(gameLog);
|
gameLogs.push(gameLog);
|
||||||
}
|
}
|
||||||
|
if (rawGameLogs.length === 0) {
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return gameLogs;
|
return gameLogs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async setDateTill(dateTill) {
|
||||||
|
await LogWatcher.SetDateTill(dateTill);
|
||||||
|
}
|
||||||
|
|
||||||
async reset() {
|
async reset() {
|
||||||
await LogWatcher.Reset();
|
await LogWatcher.Reset();
|
||||||
contextMap.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+131
-699
@@ -8,11 +8,10 @@ import Noty from 'noty';
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import ElementUI from 'element-ui';
|
import ElementUI from 'element-ui';
|
||||||
import locale from 'element-ui/lib/locale/lang/en';
|
import locale from 'element-ui/lib/locale/lang/en';
|
||||||
|
import MarqueeText from 'vue-marquee-text-component';
|
||||||
|
Vue.component('marquee-text', MarqueeText);
|
||||||
|
|
||||||
import {appVersion} from './constants.js';
|
|
||||||
import sharedRepository from './repository/shared.js';
|
|
||||||
import configRepository from './repository/config.js';
|
import configRepository from './repository/config.js';
|
||||||
import webApiService from './service/webapi.js';
|
|
||||||
|
|
||||||
speechSynthesis.getVoices();
|
speechSynthesis.getVoices();
|
||||||
|
|
||||||
@@ -109,273 +108,113 @@ speechSynthesis.getVoices();
|
|||||||
};
|
};
|
||||||
Vue.filter('timeToText', timeToText);
|
Vue.filter('timeToText', timeToText);
|
||||||
|
|
||||||
//
|
Vue.component('location', {
|
||||||
// API
|
template:
|
||||||
//
|
'<span>{{ text }}<slot></slot><span class="famfamfam-flags" :class="region" style="display:inline-block;margin-left:5px"></span></span>',
|
||||||
|
props: {
|
||||||
var API = {};
|
location: String,
|
||||||
|
hint: {
|
||||||
API.eventHandlers = new Map();
|
type: String,
|
||||||
|
default: ''
|
||||||
API.$emit = function (name, ...args) {
|
|
||||||
// console.log(name, ...args);
|
|
||||||
var handlers = this.eventHandlers.get(name);
|
|
||||||
if (typeof handlers === 'undefined') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
for (var handler of handlers) {
|
|
||||||
handler.apply(this, args);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
text: this.location,
|
||||||
|
region: this.region
|
||||||
};
|
};
|
||||||
|
},
|
||||||
API.$on = function (name, handler) {
|
methods: {
|
||||||
var handlers = this.eventHandlers.get(name);
|
parse() {
|
||||||
if (typeof handlers === 'undefined') {
|
this.text = this.location;
|
||||||
handlers = [];
|
var L = $app.parseLocation(this.location);
|
||||||
this.eventHandlers.set(name, handlers);
|
if (L.isOffline) {
|
||||||
}
|
this.text = 'Offline';
|
||||||
handlers.push(handler);
|
} else if (L.isPrivate) {
|
||||||
};
|
this.text = 'Private';
|
||||||
|
} else if (typeof this.hint === 'string' && this.hint !== '') {
|
||||||
API.$off = function (name, handler) {
|
if (L.instanceId) {
|
||||||
var handlers = this.eventHandlers.get(name);
|
this.text = `${this.hint} #${L.instanceName} ${L.accessType}`;
|
||||||
if (typeof handlers === 'undefined') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var {length} = handlers;
|
|
||||||
for (var i = 0; i < length; ++i) {
|
|
||||||
if (handlers[i] === handler) {
|
|
||||||
if (length > 1) {
|
|
||||||
handlers.splice(i, 1);
|
|
||||||
} else {
|
} else {
|
||||||
this.eventHandlers.delete(name);
|
this.text = this.hint;
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
API.pendingGetRequests = new Map();
|
|
||||||
|
|
||||||
API.call = function (endpoint, options) {
|
|
||||||
var init = {
|
|
||||||
url: `https://api.vrchat.cloud/api/1/${endpoint}`,
|
|
||||||
method: 'GET',
|
|
||||||
...options
|
|
||||||
};
|
|
||||||
var {params} = init;
|
|
||||||
var isGetRequest = init.method === 'GET';
|
|
||||||
if (isGetRequest === true) {
|
|
||||||
// transform body to url
|
|
||||||
if (params === Object(params)) {
|
|
||||||
var url = new URL(init.url);
|
|
||||||
var {searchParams} = url;
|
|
||||||
for (var key in params) {
|
|
||||||
searchParams.set(key, params[key]);
|
|
||||||
}
|
|
||||||
init.url = url.toString();
|
|
||||||
}
|
|
||||||
// merge requests
|
|
||||||
var req = this.pendingGetRequests.get(init.url);
|
|
||||||
if (typeof req !== 'undefined') {
|
|
||||||
return req;
|
|
||||||
}
|
}
|
||||||
|
} else if (L.worldId) {
|
||||||
|
if (L.instanceId) {
|
||||||
|
this.text = ` #${L.instanceName} ${L.accessType}`;
|
||||||
} else {
|
} else {
|
||||||
init.headers = {
|
this.text = this.location;
|
||||||
'Content-Type': 'application/json;charset=utf-8',
|
|
||||||
...init.headers
|
|
||||||
};
|
|
||||||
init.body =
|
|
||||||
params === Object(params) ? JSON.stringify(params) : '{}';
|
|
||||||
}
|
|
||||||
init.headers = {
|
|
||||||
'User-Agent': appVersion,
|
|
||||||
...init.headers
|
|
||||||
};
|
|
||||||
var req = webApiService
|
|
||||||
.execute(init)
|
|
||||||
.catch((err) => {
|
|
||||||
this.$throw(0, err);
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
try {
|
|
||||||
response.data = JSON.parse(response.data);
|
|
||||||
return response;
|
|
||||||
} catch (e) {}
|
|
||||||
if (response.status === 200) {
|
|
||||||
this.$throw(0, 'Invalid JSON response');
|
|
||||||
}
|
|
||||||
this.$throw(response.status);
|
|
||||||
return {};
|
|
||||||
})
|
|
||||||
.then(({data, status}) => {
|
|
||||||
if (data === Object(data)) {
|
|
||||||
if (status === 200) {
|
|
||||||
if (data.success === Object(data.success)) {
|
|
||||||
new Noty({
|
|
||||||
type: 'success',
|
|
||||||
text: escapeTag(data.success.message)
|
|
||||||
}).show();
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
if (data.error === Object(data.error)) {
|
|
||||||
this.$throw(
|
|
||||||
data.error.status_code || status,
|
|
||||||
data.error.message,
|
|
||||||
data.error.data
|
|
||||||
);
|
|
||||||
} else if (typeof data.error === 'string') {
|
|
||||||
this.$throw(data.status_code || status, data.error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.$throw(status, data);
|
this.region = '';
|
||||||
return data;
|
if (
|
||||||
});
|
this.location !== '' &&
|
||||||
if (isGetRequest === true) {
|
L.instanceId &&
|
||||||
req.finally(() => {
|
!L.isOffline &&
|
||||||
this.pendingGetRequests.delete(init.url);
|
!L.isPrivate
|
||||||
});
|
) {
|
||||||
this.pendingGetRequests.set(init.url, req);
|
if (L.region === 'eu') {
|
||||||
}
|
this.region = 'europeanunion';
|
||||||
return req;
|
} else if (L.region === 'jp') {
|
||||||
};
|
this.region = 'jp';
|
||||||
|
|
||||||
API.statusCodes = {
|
|
||||||
100: 'Continue',
|
|
||||||
101: 'Switching Protocols',
|
|
||||||
102: 'Processing',
|
|
||||||
103: 'Early Hints',
|
|
||||||
200: 'OK',
|
|
||||||
201: 'Created',
|
|
||||||
202: 'Accepted',
|
|
||||||
203: 'Non-Authoritative Information',
|
|
||||||
204: 'No Content',
|
|
||||||
205: 'Reset Content',
|
|
||||||
206: 'Partial Content',
|
|
||||||
207: 'Multi-Status',
|
|
||||||
208: 'Already Reported',
|
|
||||||
226: 'IM Used',
|
|
||||||
300: 'Multiple Choices',
|
|
||||||
301: 'Moved Permanently',
|
|
||||||
302: 'Found',
|
|
||||||
303: 'See Other',
|
|
||||||
304: 'Not Modified',
|
|
||||||
305: 'Use Proxy',
|
|
||||||
306: 'Switch Proxy',
|
|
||||||
307: 'Temporary Redirect',
|
|
||||||
308: 'Permanent Redirect',
|
|
||||||
400: 'Bad Request',
|
|
||||||
401: 'Unauthorized',
|
|
||||||
402: 'Payment Required',
|
|
||||||
403: 'Forbidden',
|
|
||||||
404: 'Not Found',
|
|
||||||
405: 'Method Not Allowed',
|
|
||||||
406: 'Not Acceptable',
|
|
||||||
407: 'Proxy Authentication Required',
|
|
||||||
408: 'Request Timeout',
|
|
||||||
409: 'Conflict',
|
|
||||||
410: 'Gone',
|
|
||||||
411: 'Length Required',
|
|
||||||
412: 'Precondition Failed',
|
|
||||||
413: 'Payload Too Large',
|
|
||||||
414: 'URI Too Long',
|
|
||||||
415: 'Unsupported Media Type',
|
|
||||||
416: 'Range Not Satisfiable',
|
|
||||||
417: 'Expectation Failed',
|
|
||||||
418: "I'm a teapot",
|
|
||||||
421: 'Misdirected Request',
|
|
||||||
422: 'Unprocessable Entity',
|
|
||||||
423: 'Locked',
|
|
||||||
424: 'Failed Dependency',
|
|
||||||
425: 'Too Early',
|
|
||||||
426: 'Upgrade Required',
|
|
||||||
428: 'Precondition Required',
|
|
||||||
429: 'Too Many Requests',
|
|
||||||
431: 'Request Header Fields Too Large',
|
|
||||||
451: 'Unavailable For Legal Reasons',
|
|
||||||
500: 'Internal Server Error',
|
|
||||||
501: 'Not Implemented',
|
|
||||||
502: 'Bad Gateway',
|
|
||||||
503: 'Service Unavailable',
|
|
||||||
504: 'Gateway Timeout',
|
|
||||||
505: 'HTTP Version Not Supported',
|
|
||||||
506: 'Variant Also Negotiates',
|
|
||||||
507: 'Insufficient Storage',
|
|
||||||
508: 'Loop Detected',
|
|
||||||
510: 'Not Extended',
|
|
||||||
511: 'Network Authentication Required',
|
|
||||||
// CloudFlare Error
|
|
||||||
520: 'Web server returns an unknown error',
|
|
||||||
521: 'Web server is down',
|
|
||||||
522: 'Connection timed out',
|
|
||||||
523: 'Origin is unreachable',
|
|
||||||
524: 'A timeout occurred',
|
|
||||||
525: 'SSL handshake failed',
|
|
||||||
526: 'Invalid SSL certificate',
|
|
||||||
527: 'Railgun Listener to origin error'
|
|
||||||
};
|
|
||||||
|
|
||||||
API.$throw = function (code, error) {
|
|
||||||
var text = [];
|
|
||||||
if (code > 0) {
|
|
||||||
var status = this.statusCodes[code];
|
|
||||||
if (typeof status === 'undefined') {
|
|
||||||
text.push(`${code}`);
|
|
||||||
} else {
|
} else {
|
||||||
text.push(`${code} ${status}`);
|
this.region = 'us';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeof error !== 'undefined') {
|
|
||||||
text.push(JSON.stringify(error));
|
|
||||||
}
|
}
|
||||||
text = text.map((s) => escapeTag(s)).join('<br>');
|
},
|
||||||
if (text.length) {
|
watch: {
|
||||||
new Noty({
|
location() {
|
||||||
type: 'error',
|
this.parse();
|
||||||
text
|
}
|
||||||
}).show();
|
},
|
||||||
|
created() {
|
||||||
|
this.parse();
|
||||||
}
|
}
|
||||||
throw new Error(text);
|
|
||||||
};
|
|
||||||
|
|
||||||
// API: Config
|
|
||||||
|
|
||||||
API.cachedConfig = {};
|
|
||||||
|
|
||||||
API.$on('CONFIG', function (args) {
|
|
||||||
args.ref = this.applyConfig(args.json);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
API.applyConfig = function (json) {
|
var $app = {
|
||||||
var ref = {
|
data: {
|
||||||
clientApiKey: '',
|
// 1 = 대시보드랑 손목에 보이는거
|
||||||
...json
|
// 2 = 항상 화면에 보이는 거
|
||||||
};
|
appType: location.href.substr(-1),
|
||||||
this.cachedConfig = ref;
|
currentTime: new Date().toJSON(),
|
||||||
return ref;
|
cpuUsage: 0,
|
||||||
|
config: {},
|
||||||
|
nowPlaying: {
|
||||||
|
url: '',
|
||||||
|
name: '',
|
||||||
|
length: 0,
|
||||||
|
startTime: 0,
|
||||||
|
elapsed: 0,
|
||||||
|
percentage: 0,
|
||||||
|
remainingText: ''
|
||||||
|
},
|
||||||
|
lastLocation: {
|
||||||
|
date: 0,
|
||||||
|
location: '',
|
||||||
|
name: '',
|
||||||
|
playerList: [],
|
||||||
|
friendList: []
|
||||||
|
},
|
||||||
|
lastLocationTimer: '',
|
||||||
|
wristFeed: [],
|
||||||
|
devices: []
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
methods: {},
|
||||||
|
watch: {},
|
||||||
|
el: '#x-app',
|
||||||
|
mounted() {
|
||||||
|
setTimeout(function () {
|
||||||
|
AppApi.ExecuteAppFunction('vrInit', '');
|
||||||
|
}, 1000);
|
||||||
|
if (this.appType === '1') {
|
||||||
|
this.updateStatsLoop();
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
API.getConfig = function () {
|
$app.methods.parseLocation = function (tag) {
|
||||||
return this.call('config', {
|
|
||||||
method: 'GET'
|
|
||||||
}).then((json) => {
|
|
||||||
var args = {
|
|
||||||
ref: null,
|
|
||||||
json
|
|
||||||
};
|
|
||||||
this.$emit('CONFIG', args);
|
|
||||||
return args;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// API: Location
|
|
||||||
|
|
||||||
API.parseLocation = function (tag) {
|
|
||||||
var _tag = String(tag || '');
|
var _tag = String(tag || '');
|
||||||
var ctx = {
|
var ctx = {
|
||||||
tag: _tag,
|
tag: _tag,
|
||||||
@@ -448,380 +287,36 @@ speechSynthesis.getVoices();
|
|||||||
return ctx;
|
return ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
Vue.component('location', {
|
$app.methods.configUpdate = function (json) {
|
||||||
template:
|
this.config = JSON.parse(json);
|
||||||
'<span>{{ text }}<slot></slot><span class="famfamfam-flags" :class="region" style="display:inline-block;margin-left:5px"></span></span>',
|
|
||||||
props: {
|
|
||||||
location: String,
|
|
||||||
hint: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
text: this.location,
|
|
||||||
region: this.region
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
parse() {
|
|
||||||
this.text = this.location;
|
|
||||||
var L = API.parseLocation(this.location);
|
|
||||||
if (L.isOffline) {
|
|
||||||
this.text = 'Offline';
|
|
||||||
} else if (L.isPrivate) {
|
|
||||||
this.text = 'Private';
|
|
||||||
} else if (typeof this.hint === 'string' && this.hint !== '') {
|
|
||||||
if (L.instanceId) {
|
|
||||||
this.text = `${this.hint} #${L.instanceName} ${L.accessType}`;
|
|
||||||
} else {
|
|
||||||
this.text = this.hint;
|
|
||||||
}
|
|
||||||
} else if (L.worldId) {
|
|
||||||
if (L.instanceId) {
|
|
||||||
this.text = ` #${L.instanceName} ${L.accessType}`;
|
|
||||||
} else {
|
|
||||||
this.text = this.location;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.region = '';
|
|
||||||
if (
|
|
||||||
this.location !== '' &&
|
|
||||||
L.instanceId &&
|
|
||||||
!L.isOffline &&
|
|
||||||
!L.isPrivate
|
|
||||||
) {
|
|
||||||
if (L.region === 'eu') {
|
|
||||||
this.region = 'europeanunion';
|
|
||||||
} else if (L.region === 'jp') {
|
|
||||||
this.region = 'jp';
|
|
||||||
} else {
|
|
||||||
this.region = 'us';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
location() {
|
|
||||||
this.parse();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.parse();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// API: World
|
|
||||||
|
|
||||||
API.cachedWorlds = new Map();
|
|
||||||
|
|
||||||
API.$on('WORLD', function (args) {
|
|
||||||
args.ref = this.applyWorld(args.json);
|
|
||||||
});
|
|
||||||
|
|
||||||
API.applyWorld = function (json) {
|
|
||||||
var ref = this.cachedWorlds.get(json.id);
|
|
||||||
if (typeof ref === 'undefined') {
|
|
||||||
ref = {
|
|
||||||
id: '',
|
|
||||||
name: '',
|
|
||||||
description: '',
|
|
||||||
authorId: '',
|
|
||||||
authorName: '',
|
|
||||||
capacity: 0,
|
|
||||||
tags: [],
|
|
||||||
releaseStatus: '',
|
|
||||||
imageUrl: '',
|
|
||||||
thumbnailImageUrl: '',
|
|
||||||
assetUrl: '',
|
|
||||||
assetUrlObject: {},
|
|
||||||
pluginUrl: '',
|
|
||||||
pluginUrlObject: {},
|
|
||||||
unityPackageUrl: '',
|
|
||||||
unityPackageUrlObject: {},
|
|
||||||
unityPackages: [],
|
|
||||||
version: 0,
|
|
||||||
favorites: 0,
|
|
||||||
created_at: '',
|
|
||||||
updated_at: '',
|
|
||||||
publicationDate: '',
|
|
||||||
labsPublicationDate: '',
|
|
||||||
visits: 0,
|
|
||||||
popularity: 0,
|
|
||||||
heat: 0,
|
|
||||||
publicOccupants: 0,
|
|
||||||
privateOccupants: 0,
|
|
||||||
occupants: 0,
|
|
||||||
instances: [],
|
|
||||||
// VRCX
|
|
||||||
$isLabs: false,
|
|
||||||
//
|
|
||||||
...json
|
|
||||||
};
|
|
||||||
this.cachedWorlds.set(ref.id, ref);
|
|
||||||
} else {
|
|
||||||
Object.assign(ref, json);
|
|
||||||
}
|
|
||||||
ref.$isLabs = ref.tags.includes('system_labs');
|
|
||||||
return ref;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
$app.methods.nowPlayingUpdate = function (json) {
|
||||||
params: {
|
this.nowPlaying = JSON.parse(json);
|
||||||
worldId: string
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
API.getWorld = function (params) {
|
|
||||||
return this.call(`worlds/${params.worldId}`, {
|
|
||||||
method: 'GET'
|
|
||||||
}).then((json) => {
|
|
||||||
var args = {
|
|
||||||
ref: null,
|
|
||||||
json,
|
|
||||||
params
|
|
||||||
};
|
|
||||||
this.$emit('WORLD', args);
|
|
||||||
return args;
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// API: User
|
$app.methods.lastLocationUpdate = function (json) {
|
||||||
|
this.lastLocation = JSON.parse(json);
|
||||||
API.cachedUsers = new Map();
|
|
||||||
|
|
||||||
API.$on('USER', function (args) {
|
|
||||||
args.ref = this.applyUser(args.json);
|
|
||||||
});
|
|
||||||
|
|
||||||
API.applyUser = function (json) {
|
|
||||||
var ref = this.cachedUsers.get(json.id);
|
|
||||||
if (typeof ref === 'undefined') {
|
|
||||||
ref = {
|
|
||||||
id: '',
|
|
||||||
username: '',
|
|
||||||
displayName: '',
|
|
||||||
userIcon: '',
|
|
||||||
bio: '',
|
|
||||||
bioLinks: [],
|
|
||||||
currentAvatarImageUrl: '',
|
|
||||||
currentAvatarThumbnailImageUrl: '',
|
|
||||||
status: '',
|
|
||||||
statusDescription: '',
|
|
||||||
state: '',
|
|
||||||
tags: [],
|
|
||||||
developerType: '',
|
|
||||||
last_login: '',
|
|
||||||
last_platform: '',
|
|
||||||
allowAvatarCopying: false,
|
|
||||||
isFriend: false,
|
|
||||||
location: '',
|
|
||||||
worldId: '',
|
|
||||||
instanceId: '',
|
|
||||||
// VRCX
|
|
||||||
...json
|
|
||||||
};
|
|
||||||
this.cachedUsers.set(ref.id, ref);
|
|
||||||
} else {
|
|
||||||
var props = {};
|
|
||||||
for (var prop in ref) {
|
|
||||||
if (ref[prop] !== Object(ref[prop])) {
|
|
||||||
props[prop] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var $ref = {...ref};
|
|
||||||
Object.assign(ref, json);
|
|
||||||
for (var prop in ref) {
|
|
||||||
if (ref[prop] !== Object(ref[prop])) {
|
|
||||||
props[prop] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (var prop in props) {
|
|
||||||
var asis = $ref[prop];
|
|
||||||
var tobe = ref[prop];
|
|
||||||
if (asis === tobe) {
|
|
||||||
delete props[prop];
|
|
||||||
} else {
|
|
||||||
props[prop] = [tobe, asis];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ref;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
$app.methods.wristFeedUpdate = function (json) {
|
||||||
params: {
|
this.wristFeed = JSON.parse(json);
|
||||||
userId: string
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
API.getUser = function (params) {
|
|
||||||
return this.call(`users/${params.userId}`, {
|
|
||||||
method: 'GET'
|
|
||||||
}).then((json) => {
|
|
||||||
var args = {
|
|
||||||
json,
|
|
||||||
params
|
|
||||||
};
|
|
||||||
this.$emit('USER', args);
|
|
||||||
return args;
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
$app.methods.updateStatsLoop = async function () {
|
||||||
params: {
|
try {
|
||||||
userId: string
|
this.currentTime = new Date().toJSON();
|
||||||
}
|
var cpuUsage = await AppApi.CpuUsage();
|
||||||
*/
|
this.cpuUsage = cpuUsage.toFixed(0);
|
||||||
API.getCachedUser = function (params) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
var ref = this.cachedUsers.get(params.userId);
|
|
||||||
if (typeof ref === 'undefined') {
|
|
||||||
this.getUser(params).catch(reject).then(resolve);
|
|
||||||
} else {
|
|
||||||
resolve({
|
|
||||||
cache: true,
|
|
||||||
json: ref,
|
|
||||||
params,
|
|
||||||
ref
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var $app = {
|
this.lastLocationTimer = '';
|
||||||
data: {
|
|
||||||
API,
|
|
||||||
// 1 = 대시보드랑 손목에 보이는거
|
|
||||||
// 2 = 항상 화면에 보이는 거
|
|
||||||
appType: location.href.substr(-1),
|
|
||||||
currentTime: new Date().toJSON(),
|
|
||||||
currentUserStatus: null,
|
|
||||||
cpuUsage: 0,
|
|
||||||
config: {},
|
|
||||||
isGameRunning: false,
|
|
||||||
isGameNoVR: false,
|
|
||||||
downloadProgress: 0,
|
|
||||||
lastLocation: {
|
|
||||||
date: 0,
|
|
||||||
location: '',
|
|
||||||
name: '',
|
|
||||||
playerList: [],
|
|
||||||
friendList: []
|
|
||||||
},
|
|
||||||
lastLocationTimer: '',
|
|
||||||
wristFeedLastEntry: '',
|
|
||||||
notyFeedLastEntry: '',
|
|
||||||
wristFeed: [],
|
|
||||||
notyMap: [],
|
|
||||||
devices: []
|
|
||||||
},
|
|
||||||
computed: {},
|
|
||||||
methods: {},
|
|
||||||
watch: {},
|
|
||||||
el: '#x-app',
|
|
||||||
mounted() {
|
|
||||||
// https://media.discordapp.net/attachments/581757976625283083/611170278218924033/unknown.png
|
|
||||||
// 현재 날짜 시간
|
|
||||||
// 컨트롤러 배터리 상황
|
|
||||||
// --
|
|
||||||
// OO is in Let's Just H!!!!! [GPS]
|
|
||||||
// OO has logged in [Online] -> TODO: location
|
|
||||||
// OO has logged out [Offline] -> TODO: location
|
|
||||||
// OO has joined [OnPlayerJoined]
|
|
||||||
// OO has left [OnPlayerLeft]
|
|
||||||
// [Moderation]
|
|
||||||
// OO has blocked you
|
|
||||||
// OO has muted you
|
|
||||||
// OO has hidden you
|
|
||||||
// --
|
|
||||||
API.getConfig()
|
|
||||||
.catch((err) => {
|
|
||||||
// FIXME: 어케 복구하냐 이건
|
|
||||||
throw err;
|
|
||||||
})
|
|
||||||
.then((args) => {
|
|
||||||
if (this.appType === '1') {
|
|
||||||
this.updateCpuUsageLoop();
|
|
||||||
}
|
|
||||||
this.initLoop();
|
|
||||||
return args;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$app.methods.updateVRConfigVars = function () {
|
|
||||||
this.currentUserStatus = sharedRepository.getString(
|
|
||||||
'current_user_status'
|
|
||||||
);
|
|
||||||
this.isGameRunning = sharedRepository.getBool('is_game_running');
|
|
||||||
this.isGameNoVR = sharedRepository.getBool('is_Game_No_VR');
|
|
||||||
this.downloadProgress = sharedRepository.getInt('downloadProgress');
|
|
||||||
var lastLocation = sharedRepository.getObject('last_location');
|
|
||||||
if (lastLocation) {
|
|
||||||
this.lastLocation = lastLocation;
|
|
||||||
if (this.lastLocation.date !== 0) {
|
if (this.lastLocation.date !== 0) {
|
||||||
this.lastLocationTimer = timeToText(
|
this.lastLocationTimer = timeToText(
|
||||||
Date.now() - this.lastLocation.date
|
Date.now() - this.lastLocation.date
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
this.lastLocationTimer = '';
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
var newConfig = sharedRepository.getObject('VRConfigVars');
|
|
||||||
if (newConfig) {
|
|
||||||
if (JSON.stringify(newConfig) !== JSON.stringify(this.config)) {
|
|
||||||
this.config = newConfig;
|
|
||||||
this.notyFeedLastEntry = '';
|
|
||||||
this.wristFeedLastEntry = '';
|
|
||||||
if (this.appType === '2') {
|
|
||||||
this.initNotyMap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw 'config not set';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$app.methods.initNotyMap = function () {
|
if (!this.config.hideDevicesFromFeed) {
|
||||||
var notyFeed = sharedRepository.getArray('notyFeed');
|
|
||||||
if (notyFeed === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
notyFeed.forEach((feed) => {
|
|
||||||
var displayName = '';
|
|
||||||
if (feed.displayName) {
|
|
||||||
displayName = feed.displayName;
|
|
||||||
} else if (feed.senderUsername) {
|
|
||||||
displayName = feed.senderUsername;
|
|
||||||
} else if (feed.sourceDisplayName) {
|
|
||||||
displayName = feed.sourceDisplayName;
|
|
||||||
} else if (feed.data) {
|
|
||||||
displayName = feed.data;
|
|
||||||
} else {
|
|
||||||
console.error('missing displayName');
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
(displayName && !this.notyMap[displayName]) ||
|
|
||||||
this.notyMap[displayName] < feed.created_at
|
|
||||||
) {
|
|
||||||
this.notyMap[displayName] = feed.created_at;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$app.methods.initLoop = function () {
|
|
||||||
if (!sharedRepository.getBool('VRInit')) {
|
|
||||||
setTimeout(this.initLoop, 500);
|
|
||||||
} else {
|
|
||||||
this.updateLoop();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$app.methods.updateLoop = async function () {
|
|
||||||
try {
|
|
||||||
this.currentTime = new Date().toJSON();
|
|
||||||
await this.updateVRConfigVars();
|
|
||||||
if (!this.config.hideDevicesFromFeed && this.appType === '1') {
|
|
||||||
AppApi.GetVRDevices().then((devices) => {
|
AppApi.GetVRDevices().then((devices) => {
|
||||||
devices.forEach((device) => {
|
devices.forEach((device) => {
|
||||||
device[2] = parseInt(device[2], 10);
|
device[2] = parseInt(device[2], 10);
|
||||||
@@ -831,96 +326,25 @@ speechSynthesis.getVoices();
|
|||||||
} else {
|
} else {
|
||||||
this.devices = '';
|
this.devices = '';
|
||||||
}
|
}
|
||||||
await this.updateSharedFeeds();
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
setTimeout(() => this.updateLoop(), 500);
|
setTimeout(() => this.updateStatsLoop(), 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.methods.updateCpuUsageLoop = async function () {
|
$app.methods.playNoty = function (json) {
|
||||||
try {
|
var {noty, message, image} = JSON.parse(json);
|
||||||
var cpuUsage = await AppApi.CpuUsage();
|
|
||||||
this.cpuUsage = cpuUsage.toFixed(0);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
setTimeout(() => this.updateCpuUsageLoop(), 1000);
|
|
||||||
};
|
|
||||||
|
|
||||||
$app.methods.updateSharedFeeds = function () {
|
|
||||||
if (this.appType === '1') {
|
|
||||||
this.wristFeed = sharedRepository.getArray('wristFeed');
|
|
||||||
}
|
|
||||||
if (this.appType === '2') {
|
|
||||||
var notyFeed = sharedRepository.getArray('notyFeed');
|
|
||||||
this.updateSharedFeedNoty(notyFeed);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$app.methods.updateSharedFeedNoty = function (notyFeed) {
|
|
||||||
var notyToPlay = [];
|
|
||||||
notyFeed.forEach((feed) => {
|
|
||||||
var displayName = '';
|
|
||||||
if (feed.displayName) {
|
|
||||||
displayName = feed.displayName;
|
|
||||||
} else if (feed.senderUsername) {
|
|
||||||
displayName = feed.senderUsername;
|
|
||||||
} else if (feed.sourceDisplayName) {
|
|
||||||
displayName = feed.sourceDisplayName;
|
|
||||||
} else if (feed.data) {
|
|
||||||
displayName = feed.data;
|
|
||||||
} else {
|
|
||||||
console.error('missing displayName');
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
(displayName && !this.notyMap[displayName]) ||
|
|
||||||
this.notyMap[displayName] < feed.created_at
|
|
||||||
) {
|
|
||||||
this.notyMap[displayName] = feed.created_at;
|
|
||||||
notyToPlay.push(feed);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// disable notifications when busy
|
|
||||||
if (this.currentUserStatus === 'busy') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var bias = new Date(Date.now() - 60000).toJSON();
|
|
||||||
var noty = {};
|
|
||||||
var messageList = [
|
|
||||||
'inviteMessage',
|
|
||||||
'requestMessage',
|
|
||||||
'responseMessage'
|
|
||||||
];
|
|
||||||
for (var i = 0; i < notyToPlay.length; i++) {
|
|
||||||
noty = notyToPlay[i];
|
|
||||||
if (noty.created_at < bias) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var message = '';
|
|
||||||
for (var k = 0; k < messageList.length; k++) {
|
|
||||||
if (
|
|
||||||
typeof noty.details !== 'undefined' &&
|
|
||||||
typeof noty.details[messageList[k]] !== 'undefined'
|
|
||||||
) {
|
|
||||||
message = noty.details[messageList[k]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (message) {
|
|
||||||
message = `, ${message}`;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
this.config.overlayNotifications &&
|
|
||||||
!this.isGameNoVR &&
|
|
||||||
this.isGameRunning
|
|
||||||
) {
|
|
||||||
var text = '';
|
var text = '';
|
||||||
|
var img = '';
|
||||||
|
if (image) {
|
||||||
|
img = `<img class="noty-img" src="data:image/png;base64, ${image}"></img>`;
|
||||||
|
}
|
||||||
switch (noty.type) {
|
switch (noty.type) {
|
||||||
case 'OnPlayerJoined':
|
case 'OnPlayerJoined':
|
||||||
text = `<strong>${noty.data}</strong> has joined`;
|
text = `<strong>${noty.displayName}</strong> has joined`;
|
||||||
break;
|
break;
|
||||||
case 'OnPlayerLeft':
|
case 'OnPlayerLeft':
|
||||||
text = `<strong>${noty.data}</strong> has left`;
|
text = `<strong>${noty.displayName}</strong> has left`;
|
||||||
break;
|
break;
|
||||||
case 'OnPlayerJoining':
|
case 'OnPlayerJoining':
|
||||||
text = `<strong>${noty.displayName}</strong> is joining`;
|
text = `<strong>${noty.displayName}</strong> is joining`;
|
||||||
@@ -975,13 +399,23 @@ speechSynthesis.getVoices();
|
|||||||
text = `<strong>${noty.previousDisplayName}</strong> changed their name to ${noty.displayName}`;
|
text = `<strong>${noty.previousDisplayName}</strong> changed their name to ${noty.displayName}`;
|
||||||
break;
|
break;
|
||||||
case 'PortalSpawn':
|
case 'PortalSpawn':
|
||||||
text = `<strong>${noty.data}</strong> has spawned a portal`;
|
var locationName = '';
|
||||||
|
if (noty.worldName) {
|
||||||
|
locationName = ` to ${this.displayLocation(
|
||||||
|
noty.instanceId,
|
||||||
|
noty.worldName
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
text = `<strong>${noty.displayName}</strong> has spawned a portal${locationName}`;
|
||||||
|
break;
|
||||||
|
case 'AvatarChange':
|
||||||
|
text = `<strong>${noty.displayName}</strong> changed into avatar ${noty.name}`;
|
||||||
break;
|
break;
|
||||||
case 'Event':
|
case 'Event':
|
||||||
text = noty.data;
|
text = noty.data;
|
||||||
break;
|
break;
|
||||||
case 'VideoPlay':
|
case 'VideoPlay':
|
||||||
text = `<strong>Now playing:</strong> ${noty.data}`;
|
text = `<strong>Now playing:</strong> ${noty.notyName}`;
|
||||||
break;
|
break;
|
||||||
case 'BlockedOnPlayerJoined':
|
case 'BlockedOnPlayerJoined':
|
||||||
text = `Blocked user <strong>${noty.displayName}</strong> has joined`;
|
text = `Blocked user <strong>${noty.displayName}</strong> has joined`;
|
||||||
@@ -1004,11 +438,9 @@ speechSynthesis.getVoices();
|
|||||||
theme: this.config.notificationTheme,
|
theme: this.config.notificationTheme,
|
||||||
timeout: this.config.notificationTimeout,
|
timeout: this.config.notificationTimeout,
|
||||||
layout: this.config.notificationPosition,
|
layout: this.config.notificationPosition,
|
||||||
text
|
text: `${img}<div class="noty-text">${text}</div>`
|
||||||
}).show();
|
}).show();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$app.methods.statusClass = function (status) {
|
$app.methods.statusClass = function (status) {
|
||||||
@@ -1033,7 +465,7 @@ speechSynthesis.getVoices();
|
|||||||
|
|
||||||
$app.methods.displayLocation = function (location, worldName) {
|
$app.methods.displayLocation = function (location, worldName) {
|
||||||
var text = '';
|
var text = '';
|
||||||
var L = API.parseLocation(location);
|
var L = this.parseLocation(location);
|
||||||
if (L.isOffline) {
|
if (L.isOffline) {
|
||||||
text = 'Offline';
|
text = 'Offline';
|
||||||
} else if (L.isPrivate) {
|
} else if (L.isPrivate) {
|
||||||
|
|||||||
+70
-18
@@ -36,17 +36,23 @@ html
|
|||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
||||||
| #[span.name(v-text="feed.displayName")] #[i.x-user-status(:class="statusClass(feed.status)")] {{feed.statusDescription}}
|
| #[span.name(v-text="feed.displayName")]
|
||||||
|
template(v-if="feed.statusDescription === feed.previousStatusDescription")
|
||||||
|
i.x-user-status(:class="statusClass(feed.previousStatus)")
|
||||||
|
i.el-icon-right
|
||||||
|
i.x-user-status(:class="statusClass(feed.status)")
|
||||||
|
template(v-else)
|
||||||
|
| #[i.x-user-status(:class="statusClass(feed.status)")] {{feed.statusDescription}}
|
||||||
div(v-else-if="feed.type === 'OnPlayerJoined'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
div(v-else-if="feed.type === 'OnPlayerJoined'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
||||||
| ▶️ #[span.name(v-text="feed.data")]
|
| ▶️ #[span.name(v-text="feed.displayName")]
|
||||||
div(v-else-if="feed.type === 'OnPlayerLeft'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
div(v-else-if="feed.type === 'OnPlayerLeft'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
||||||
| ◀️ #[span.name(v-text="feed.data")]
|
| ◀️ #[span.name(v-text="feed.displayName")]
|
||||||
div(v-else-if="feed.type === 'OnPlayerJoining'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
div(v-else-if="feed.type === 'OnPlayerJoining'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
@@ -57,7 +63,16 @@ html
|
|||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
||||||
location(:location="feed.data[0]" :hint="feed.data[1]")
|
location(:location="feed.location" :hint="feed.worldName")
|
||||||
|
div(v-else-if="feed.type === 'VideoPlay'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
||||||
|
.detail
|
||||||
|
span.extra
|
||||||
|
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
||||||
|
| 🎵 #[span.name(v-text="feed.displayName")]
|
||||||
|
template(v-if="feed.videoName")
|
||||||
|
| #[span(v-text="feed.videoName")]
|
||||||
|
template(v-else)
|
||||||
|
| #[span(v-text="feed.videoUrl")]
|
||||||
div(v-else-if="feed.type === 'invite'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
div(v-else-if="feed.type === 'invite'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
@@ -107,7 +122,16 @@ html
|
|||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
||||||
| ✨ #[span.name(v-text="feed.data")]
|
| ✨ #[span.name(v-text="feed.displayName")]
|
||||||
|
template(v-if="feed.worldName")
|
||||||
|
| #[location(:location="feed.instanceId" :hint="feed.worldName")]
|
||||||
|
div(v-else-if="feed.type === 'AvatarChange'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
||||||
|
.detail
|
||||||
|
span.extra
|
||||||
|
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
||||||
|
| 🧍 #[span.name(v-text="feed.displayName")] {{ feed.name }}
|
||||||
|
template(v-if="feed.description && feed.description !== feed.name")
|
||||||
|
| - {{ feed.description }}
|
||||||
div(v-else-if="feed.type === 'Event'" class="x-friend-item")
|
div(v-else-if="feed.type === 'Event'" class="x-friend-item")
|
||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
@@ -159,17 +183,23 @@ html
|
|||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
||||||
| #[span.name(v-text="feed.displayName")] is #[i.x-user-status(:class="statusClass(feed.status)")] {{feed.statusDescription}}
|
| #[span.name(v-text="feed.displayName")]
|
||||||
|
template(v-if="feed.statusDescription === feed.previousStatusDescription")
|
||||||
|
i.x-user-status(:class="statusClass(feed.previousStatus)")
|
||||||
|
i.el-icon-right
|
||||||
|
i.x-user-status(:class="statusClass(feed.status)")
|
||||||
|
template(v-else)
|
||||||
|
| #[i.x-user-status(:class="statusClass(feed.status)")] {{feed.statusDescription}}
|
||||||
div(v-else-if="feed.type === 'OnPlayerJoined'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
div(v-else-if="feed.type === 'OnPlayerJoined'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
||||||
| #[span.name(v-text="feed.data")] has joined
|
| #[span.name(v-text="feed.displayName")] has joined
|
||||||
div(v-else-if="feed.type === 'OnPlayerLeft'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
div(v-else-if="feed.type === 'OnPlayerLeft'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
||||||
| #[span.name(v-text="feed.data")] has left
|
| #[span.name(v-text="feed.displayName")] has left
|
||||||
div(v-else-if="feed.type === 'OnPlayerJoining'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
div(v-else-if="feed.type === 'OnPlayerJoining'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
@@ -179,7 +209,16 @@ html
|
|||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
||||||
location(:location="feed.data[0]" :hint="feed.data[1]")
|
location(:location="feed.location" :hint="feed.worldName")
|
||||||
|
div(v-else-if="feed.type === 'VideoPlay'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
||||||
|
.detail
|
||||||
|
span.extra
|
||||||
|
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
||||||
|
| #[span.name(v-text="feed.displayName")] changed video to
|
||||||
|
template(v-if="feed.videoName")
|
||||||
|
| #[span(v-text="feed.videoName")]
|
||||||
|
template(v-else)
|
||||||
|
| #[span(v-text="feed.videoUrl")]
|
||||||
div(v-else-if="feed.type === 'invite'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
div(v-else-if="feed.type === 'invite'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
@@ -229,7 +268,16 @@ html
|
|||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
||||||
| #[span.name(v-text="feed.data")] has spawned a portal
|
| #[span.name(v-text="feed.displayName")] has spawned a portal
|
||||||
|
template(v-if="feed.worldName")
|
||||||
|
| to #[location(:location="feed.instanceId" :hint="feed.worldName")]
|
||||||
|
div(v-else-if="feed.type === 'AvatarChange'" class="x-friend-item" :class="{ friend: feed.isFriend, favorite: feed.isFavorite }")
|
||||||
|
.detail
|
||||||
|
span.extra
|
||||||
|
span.time {{ feed.created_at | formatDate('HH:MI') }}
|
||||||
|
| #[span.name(v-text="feed.displayName")] changed into avatar {{ feed.name }}
|
||||||
|
template(v-if="feed.description && feed.description !== feed.name")
|
||||||
|
| - {{ feed.description }}
|
||||||
div(v-else-if="feed.type === 'Event'" class="x-friend-item")
|
div(v-else-if="feed.type === 'Event'" class="x-friend-item")
|
||||||
.detail
|
.detail
|
||||||
span.extra
|
span.extra
|
||||||
@@ -301,21 +349,25 @@ html
|
|||||||
br
|
br
|
||||||
span {{ device[2] }}%
|
span {{ device[2] }}%
|
||||||
.x-containerbottom
|
.x-containerbottom
|
||||||
|
template(v-if="nowPlaying.playing")
|
||||||
|
span(style="float:right;padding-left:10px") {{ nowPlaying.remainingText }}
|
||||||
|
marquee-text {{ nowPlaying.name }}
|
||||||
|
div.np-progress-bar(:style="{ width: nowPlaying.percentage + '%' }")
|
||||||
template(v-if="config && config.minimalFeed")
|
template(v-if="config && config.minimalFeed")
|
||||||
template(v-if="downloadProgress === 100")
|
template(v-if="config.downloadProgress === 100")
|
||||||
span(style="display:inline-block;margin-right:5px") #[i.el-icon-loading]
|
span(style="display:inline-block;margin-right:5px") #[i.el-icon-loading]
|
||||||
template(v-else-if="downloadProgress > 0")
|
template(v-else-if="config.downloadProgress > 0")
|
||||||
span(style="display:inline-block;margin-right:5px") {{ downloadProgress }}%
|
span(style="display:inline-block;margin-right:5px") {{ config.downloadProgress }}%
|
||||||
template(v-if="lastLocation.date != 0")
|
template(v-if="lastLocation.date !== 0")
|
||||||
span(style="float:right") {{ lastLocationTimer }}
|
span(style="float:right") {{ lastLocationTimer }}
|
||||||
span(style="display:inline-block") {{ lastLocation.playerList.length }}
|
span(style="display:inline-block") {{ lastLocation.playerList.length }}
|
||||||
span(style="display:inline-block;font-weight:bold") {{ lastLocation.friendList.length !== 0 ? ` (${lastLocation.friendList.length})` : ''}}
|
span(style="display:inline-block;font-weight:bold") {{ lastLocation.friendList.length !== 0 ? ` (${lastLocation.friendList.length})` : ''}}
|
||||||
template(v-else)
|
template(v-else)
|
||||||
template(v-if="downloadProgress === 100")
|
template(v-if="config.downloadProgress === 100")
|
||||||
span(style="display:inline-block;margin-right:5px") Downloading: #[i.el-icon-loading]
|
span(style="display:inline-block;margin-right:5px") Downloading: #[i.el-icon-loading]
|
||||||
template(v-else-if="downloadProgress > 0")
|
template(v-else-if="config.downloadProgress > 0")
|
||||||
span(style="display:inline-block;margin-right:5px") Downloading: {{ downloadProgress }}%
|
span(style="display:inline-block;margin-right:5px") Downloading: {{ config.downloadProgress }}%
|
||||||
template(v-if="lastLocation.date != 0")
|
template(v-if="lastLocation.date !== 0")
|
||||||
span(style="float:right") Timer: {{ lastLocationTimer }}
|
span(style="float:right") Timer: {{ lastLocationTimer }}
|
||||||
span(style="display:inline-block") Players: {{ lastLocation.playerList.length }}
|
span(style="display:inline-block") Players: {{ lastLocation.playerList.length }}
|
||||||
span(style="display:inline-block;font-weight:bold") {{ lastLocation.friendList.length !== 0 ? ` (${lastLocation.friendList.length})` : ''}}
|
span(style="display:inline-block;font-weight:bold") {{ lastLocation.friendList.length !== 0 ? ` (${lastLocation.friendList.length})` : ''}}
|
||||||
|
|||||||
+21
-6
@@ -22,9 +22,6 @@
|
|||||||
|
|
||||||
.noty_body {
|
.noty_body {
|
||||||
display: block;
|
display: block;
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.noty_layout {
|
.noty_layout {
|
||||||
@@ -34,6 +31,7 @@
|
|||||||
|
|
||||||
.noty_theme__relax.noty_bar,
|
.noty_theme__relax.noty_bar,
|
||||||
.noty_theme__sunset.noty_bar {
|
.noty_theme__sunset.noty_bar {
|
||||||
|
height: 42px;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 4px 0;
|
margin: 4px 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -42,9 +40,7 @@
|
|||||||
|
|
||||||
.noty_theme__relax.noty_bar .noty_body,
|
.noty_theme__relax.noty_bar .noty_body,
|
||||||
.noty_theme__sunset.noty_bar .noty_body {
|
.noty_theme__sunset.noty_bar .noty_body {
|
||||||
padding: 5px 10px 10px;
|
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
text-align: center;
|
|
||||||
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
|
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +139,19 @@
|
|||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.noty-text {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: 8px 8px 0 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.noty-img {
|
||||||
|
height: 42px;
|
||||||
|
float: left;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
@@ -202,16 +211,22 @@ button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.x-containerbottom span {
|
.x-containerbottom span {
|
||||||
padding: 0px;
|
|
||||||
display: block;
|
display: block;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.np-progress-bar {
|
||||||
|
width: 0%;
|
||||||
|
height: 2px;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
.x-friend-item {
|
.x-friend-item {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
height: 27.1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.x-friend-item .time {
|
.x-friend-item .time {
|
||||||
|
|||||||
Reference in New Issue
Block a user