mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
Edgegap Plugin: switch to Package Manager dependency (#3845)
* remove Hosting/Edgegap * pull in the plugin via package manager * 1.0.7 --------- Co-authored-by: mischa <info@noobtuts.com>
This commit is contained in:
parent
e9c3548124
commit
890f4e6c0b
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b13bce90dfb604c2d9170e3640f59ad9
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b7c51dc3e45095f4a8a960150837fe7b
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,3 +0,0 @@
|
|||||||
# Edgegap Servers Plugin Changelog
|
|
||||||
|
|
||||||
Please refer to our [Github repository](https://github.com/edgegap/edgegap-unity-plugin/releases) for up-to-date changelog.
|
|
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e3f5a876d3822ce4e884e3c8d026fbcc
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 14024ce6d2e64d5ba58ab20409ac648f
|
|
||||||
timeCreated: 1701785018
|
|
@ -1,704 +0,0 @@
|
|||||||
// MIRROR CHANGE: drop in Codice.Utils HttpUtility subset to not depend on Unity's plastic scm package
|
|
||||||
// SOURCE: Unity Plastic SCM package
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Edgegap.Codice.Utils // MIRROR CHANGE: namespace Edgegap.* to not collide if anyone has Plastic SCM installed already
|
|
||||||
{
|
|
||||||
public class HttpEncoder
|
|
||||||
{
|
|
||||||
private static char[] hexChars = "0123456789abcdef".ToCharArray();
|
|
||||||
private static object entitiesLock = new object();
|
|
||||||
private static SortedDictionary<string, char> entities;
|
|
||||||
private static HttpEncoder defaultEncoder = new HttpEncoder();
|
|
||||||
private static HttpEncoder currentEncoder = HttpEncoder.defaultEncoder;
|
|
||||||
|
|
||||||
private static IDictionary<string, char> Entities
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
lock (HttpEncoder.entitiesLock)
|
|
||||||
{
|
|
||||||
if (HttpEncoder.entities == null)
|
|
||||||
HttpEncoder.InitEntities();
|
|
||||||
return (IDictionary<string, char>) HttpEncoder.entities;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HttpEncoder Current
|
|
||||||
{
|
|
||||||
get => HttpEncoder.currentEncoder;
|
|
||||||
set => HttpEncoder.currentEncoder = value != null ? value : throw new ArgumentNullException(nameof (value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HttpEncoder Default => HttpEncoder.defaultEncoder;
|
|
||||||
|
|
||||||
protected internal virtual void HeaderNameValueEncode(
|
|
||||||
string headerName,
|
|
||||||
string headerValue,
|
|
||||||
out string encodedHeaderName,
|
|
||||||
out string encodedHeaderValue)
|
|
||||||
{
|
|
||||||
encodedHeaderName = !string.IsNullOrEmpty(headerName) ? HttpEncoder.EncodeHeaderString(headerName) : headerName;
|
|
||||||
if (string.IsNullOrEmpty(headerValue))
|
|
||||||
encodedHeaderValue = headerValue;
|
|
||||||
else
|
|
||||||
encodedHeaderValue = HttpEncoder.EncodeHeaderString(headerValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void StringBuilderAppend(string s, ref StringBuilder sb)
|
|
||||||
{
|
|
||||||
if (sb == null)
|
|
||||||
sb = new StringBuilder(s);
|
|
||||||
else
|
|
||||||
sb.Append(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string EncodeHeaderString(string input)
|
|
||||||
{
|
|
||||||
StringBuilder sb = (StringBuilder) null;
|
|
||||||
for (int index = 0; index < input.Length; ++index)
|
|
||||||
{
|
|
||||||
char ch = input[index];
|
|
||||||
if (ch < ' ' && ch != '\t' || ch == '\u007F')
|
|
||||||
HttpEncoder.StringBuilderAppend(string.Format("%{0:x2}", (object) (int) ch), ref sb);
|
|
||||||
}
|
|
||||||
return sb != null ? sb.ToString() : input;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected internal virtual void HtmlAttributeEncode(string value, TextWriter output)
|
|
||||||
{
|
|
||||||
if (output == null)
|
|
||||||
throw new ArgumentNullException(nameof (output));
|
|
||||||
if (string.IsNullOrEmpty(value))
|
|
||||||
return;
|
|
||||||
output.Write(HttpEncoder.HtmlAttributeEncode(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected internal virtual void HtmlDecode(string value, TextWriter output)
|
|
||||||
{
|
|
||||||
if (output == null)
|
|
||||||
throw new ArgumentNullException(nameof (output));
|
|
||||||
output.Write(HttpEncoder.HtmlDecode(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected internal virtual void HtmlEncode(string value, TextWriter output)
|
|
||||||
{
|
|
||||||
if (output == null)
|
|
||||||
throw new ArgumentNullException(nameof (output));
|
|
||||||
output.Write(HttpEncoder.HtmlEncode(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected internal virtual byte[] UrlEncode(byte[] bytes, int offset, int count) => HttpEncoder.UrlEncodeToBytes(bytes, offset, count);
|
|
||||||
|
|
||||||
protected internal virtual string UrlPathEncode(string value)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(value))
|
|
||||||
return value;
|
|
||||||
MemoryStream result = new MemoryStream();
|
|
||||||
int length = value.Length;
|
|
||||||
for (int index = 0; index < length; ++index)
|
|
||||||
HttpEncoder.UrlPathEncodeChar(value[index], (Stream) result);
|
|
||||||
return Encoding.ASCII.GetString(result.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static byte[] UrlEncodeToBytes(byte[] bytes, int offset, int count)
|
|
||||||
{
|
|
||||||
int num1 = bytes != null ? bytes.Length : throw new ArgumentNullException(nameof (bytes));
|
|
||||||
if (num1 == 0)
|
|
||||||
return new byte[0];
|
|
||||||
if (offset < 0 || offset >= num1)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof (offset));
|
|
||||||
if (count < 0 || count > num1 - offset)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof (count));
|
|
||||||
MemoryStream result = new MemoryStream(count);
|
|
||||||
int num2 = offset + count;
|
|
||||||
for (int index = offset; index < num2; ++index)
|
|
||||||
HttpEncoder.UrlEncodeChar((char) bytes[index], (Stream) result, false);
|
|
||||||
return result.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string HtmlEncode(string s)
|
|
||||||
{
|
|
||||||
switch (s)
|
|
||||||
{
|
|
||||||
case "":
|
|
||||||
return string.Empty;
|
|
||||||
case null:
|
|
||||||
return (string) null;
|
|
||||||
default:
|
|
||||||
bool flag = false;
|
|
||||||
for (int index = 0; index < s.Length; ++index)
|
|
||||||
{
|
|
||||||
char ch = s[index];
|
|
||||||
if (ch == '&' || ch == '"' || ch == '<' || ch == '>' || ch > '\u009F' || ch == '\'')
|
|
||||||
{
|
|
||||||
flag = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!flag)
|
|
||||||
return s;
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
|
||||||
int length = s.Length;
|
|
||||||
for (int index = 0; index < length; ++index)
|
|
||||||
{
|
|
||||||
char ch = s[index];
|
|
||||||
switch (ch)
|
|
||||||
{
|
|
||||||
case '"':
|
|
||||||
stringBuilder.Append(""");
|
|
||||||
break;
|
|
||||||
case '&':
|
|
||||||
stringBuilder.Append("&");
|
|
||||||
break;
|
|
||||||
case '\'':
|
|
||||||
stringBuilder.Append("'");
|
|
||||||
break;
|
|
||||||
case '<':
|
|
||||||
stringBuilder.Append("<");
|
|
||||||
break;
|
|
||||||
case '>':
|
|
||||||
stringBuilder.Append(">");
|
|
||||||
break;
|
|
||||||
case '<':
|
|
||||||
stringBuilder.Append("<");
|
|
||||||
break;
|
|
||||||
case '>':
|
|
||||||
stringBuilder.Append(">");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (ch > '\u009F' && ch < 'Ā')
|
|
||||||
{
|
|
||||||
stringBuilder.Append("&#");
|
|
||||||
stringBuilder.Append(((int) ch).ToString((IFormatProvider) CultureInfo.InvariantCulture));
|
|
||||||
stringBuilder.Append(";");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
stringBuilder.Append(ch);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return stringBuilder.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string HtmlAttributeEncode(string s)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(s))
|
|
||||||
return string.Empty;
|
|
||||||
bool flag = false;
|
|
||||||
for (int index = 0; index < s.Length; ++index)
|
|
||||||
{
|
|
||||||
char ch = s[index];
|
|
||||||
int num;
|
|
||||||
switch (ch)
|
|
||||||
{
|
|
||||||
case '"':
|
|
||||||
case '&':
|
|
||||||
case '<':
|
|
||||||
num = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
num = ch != '\'' ? 1 : 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (num == 0)
|
|
||||||
{
|
|
||||||
flag = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!flag)
|
|
||||||
return s;
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
|
||||||
int length = s.Length;
|
|
||||||
for (int index = 0; index < length; ++index)
|
|
||||||
{
|
|
||||||
char ch = s[index];
|
|
||||||
switch (ch)
|
|
||||||
{
|
|
||||||
case '"':
|
|
||||||
stringBuilder.Append(""");
|
|
||||||
break;
|
|
||||||
case '&':
|
|
||||||
stringBuilder.Append("&");
|
|
||||||
break;
|
|
||||||
case '\'':
|
|
||||||
stringBuilder.Append("'");
|
|
||||||
break;
|
|
||||||
case '<':
|
|
||||||
stringBuilder.Append("<");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
stringBuilder.Append(ch);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return stringBuilder.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string HtmlDecode(string s)
|
|
||||||
{
|
|
||||||
switch (s)
|
|
||||||
{
|
|
||||||
case "":
|
|
||||||
return string.Empty;
|
|
||||||
case null:
|
|
||||||
return (string) null;
|
|
||||||
default:
|
|
||||||
if (s.IndexOf('&') == -1)
|
|
||||||
return s;
|
|
||||||
StringBuilder stringBuilder1 = new StringBuilder();
|
|
||||||
StringBuilder stringBuilder2 = new StringBuilder();
|
|
||||||
StringBuilder stringBuilder3 = new StringBuilder();
|
|
||||||
int length = s.Length;
|
|
||||||
int num1 = 0;
|
|
||||||
int num2 = 0;
|
|
||||||
bool flag1 = false;
|
|
||||||
bool flag2 = false;
|
|
||||||
for (int index = 0; index < length; ++index)
|
|
||||||
{
|
|
||||||
char ch = s[index];
|
|
||||||
if (num1 == 0)
|
|
||||||
{
|
|
||||||
if (ch == '&')
|
|
||||||
{
|
|
||||||
stringBuilder2.Append(ch);
|
|
||||||
stringBuilder1.Append(ch);
|
|
||||||
num1 = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
stringBuilder3.Append(ch);
|
|
||||||
}
|
|
||||||
else if (ch == '&')
|
|
||||||
{
|
|
||||||
num1 = 1;
|
|
||||||
if (flag2)
|
|
||||||
{
|
|
||||||
stringBuilder2.Append(num2.ToString((IFormatProvider) CultureInfo.InvariantCulture));
|
|
||||||
flag2 = false;
|
|
||||||
}
|
|
||||||
stringBuilder3.Append(stringBuilder2.ToString());
|
|
||||||
stringBuilder2.Length = 0;
|
|
||||||
stringBuilder2.Append('&');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (num1)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
if (ch == ';')
|
|
||||||
{
|
|
||||||
num1 = 0;
|
|
||||||
stringBuilder3.Append(stringBuilder2.ToString());
|
|
||||||
stringBuilder3.Append(ch);
|
|
||||||
stringBuilder2.Length = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
num2 = 0;
|
|
||||||
flag1 = false;
|
|
||||||
num1 = ch == '#' ? 3 : 2;
|
|
||||||
stringBuilder2.Append(ch);
|
|
||||||
stringBuilder1.Append(ch);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
stringBuilder2.Append(ch);
|
|
||||||
if (ch == ';')
|
|
||||||
{
|
|
||||||
string str = stringBuilder2.ToString();
|
|
||||||
if (str.Length > 1 && HttpEncoder.Entities.ContainsKey(str.Substring(1, str.Length - 2)))
|
|
||||||
str = HttpEncoder.Entities[str.Substring(1, str.Length - 2)].ToString();
|
|
||||||
stringBuilder3.Append(str);
|
|
||||||
num1 = 0;
|
|
||||||
stringBuilder2.Length = 0;
|
|
||||||
stringBuilder1.Length = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if (ch == ';')
|
|
||||||
{
|
|
||||||
if (num2 == 0)
|
|
||||||
stringBuilder3.Append(stringBuilder1.ToString() + ";");
|
|
||||||
else if (num2 > (int) ushort.MaxValue)
|
|
||||||
{
|
|
||||||
stringBuilder3.Append("&#");
|
|
||||||
stringBuilder3.Append(num2.ToString((IFormatProvider) CultureInfo.InvariantCulture));
|
|
||||||
stringBuilder3.Append(";");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
stringBuilder3.Append((char) num2);
|
|
||||||
num1 = 0;
|
|
||||||
stringBuilder2.Length = 0;
|
|
||||||
stringBuilder1.Length = 0;
|
|
||||||
flag2 = false;
|
|
||||||
}
|
|
||||||
else if (flag1 && Uri.IsHexDigit(ch))
|
|
||||||
{
|
|
||||||
num2 = num2 * 16 + Uri.FromHex(ch);
|
|
||||||
flag2 = true;
|
|
||||||
stringBuilder1.Append(ch);
|
|
||||||
}
|
|
||||||
else if (char.IsDigit(ch))
|
|
||||||
{
|
|
||||||
num2 = num2 * 10 + ((int) ch - 48);
|
|
||||||
flag2 = true;
|
|
||||||
stringBuilder1.Append(ch);
|
|
||||||
}
|
|
||||||
else if (num2 == 0 && (ch == 'x' || ch == 'X'))
|
|
||||||
{
|
|
||||||
flag1 = true;
|
|
||||||
stringBuilder1.Append(ch);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
num1 = 2;
|
|
||||||
if (flag2)
|
|
||||||
{
|
|
||||||
stringBuilder2.Append(num2.ToString((IFormatProvider) CultureInfo.InvariantCulture));
|
|
||||||
flag2 = false;
|
|
||||||
}
|
|
||||||
stringBuilder2.Append(ch);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (stringBuilder2.Length > 0)
|
|
||||||
stringBuilder3.Append(stringBuilder2.ToString());
|
|
||||||
else if (flag2)
|
|
||||||
stringBuilder3.Append(num2.ToString((IFormatProvider) CultureInfo.InvariantCulture));
|
|
||||||
return stringBuilder3.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static bool NotEncoded(char c) => c == '!' || c == '(' || c == ')' || c == '*' || c == '-' || c == '.' || c == '_';
|
|
||||||
|
|
||||||
internal static void UrlEncodeChar(char c, Stream result, bool isUnicode)
|
|
||||||
{
|
|
||||||
if (c > 'ÿ')
|
|
||||||
{
|
|
||||||
int num = (int) c;
|
|
||||||
result.WriteByte((byte) 37);
|
|
||||||
result.WriteByte((byte) 117);
|
|
||||||
int index1 = num >> 12;
|
|
||||||
result.WriteByte((byte) HttpEncoder.hexChars[index1]);
|
|
||||||
int index2 = num >> 8 & 15;
|
|
||||||
result.WriteByte((byte) HttpEncoder.hexChars[index2]);
|
|
||||||
int index3 = num >> 4 & 15;
|
|
||||||
result.WriteByte((byte) HttpEncoder.hexChars[index3]);
|
|
||||||
int index4 = num & 15;
|
|
||||||
result.WriteByte((byte) HttpEncoder.hexChars[index4]);
|
|
||||||
}
|
|
||||||
else if (c > ' ' && HttpEncoder.NotEncoded(c))
|
|
||||||
result.WriteByte((byte) c);
|
|
||||||
else if (c == ' ')
|
|
||||||
result.WriteByte((byte) 43);
|
|
||||||
else if (c < '0' || c < 'A' && c > '9' || c > 'Z' && c < 'a' || c > 'z')
|
|
||||||
{
|
|
||||||
if (isUnicode && c > '\u007F')
|
|
||||||
{
|
|
||||||
result.WriteByte((byte) 37);
|
|
||||||
result.WriteByte((byte) 117);
|
|
||||||
result.WriteByte((byte) 48);
|
|
||||||
result.WriteByte((byte) 48);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result.WriteByte((byte) 37);
|
|
||||||
int index5 = (int) c >> 4;
|
|
||||||
result.WriteByte((byte) HttpEncoder.hexChars[index5]);
|
|
||||||
int index6 = (int) c & 15;
|
|
||||||
result.WriteByte((byte) HttpEncoder.hexChars[index6]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result.WriteByte((byte) c);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void UrlPathEncodeChar(char c, Stream result)
|
|
||||||
{
|
|
||||||
if (c < '!' || c > '~')
|
|
||||||
{
|
|
||||||
byte[] bytes = Encoding.UTF8.GetBytes(c.ToString());
|
|
||||||
for (int index1 = 0; index1 < bytes.Length; ++index1)
|
|
||||||
{
|
|
||||||
result.WriteByte((byte) 37);
|
|
||||||
int index2 = (int) bytes[index1] >> 4;
|
|
||||||
result.WriteByte((byte) HttpEncoder.hexChars[index2]);
|
|
||||||
int index3 = (int) bytes[index1] & 15;
|
|
||||||
result.WriteByte((byte) HttpEncoder.hexChars[index3]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (c == ' ')
|
|
||||||
{
|
|
||||||
result.WriteByte((byte) 37);
|
|
||||||
result.WriteByte((byte) 50);
|
|
||||||
result.WriteByte((byte) 48);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result.WriteByte((byte) c);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void InitEntities()
|
|
||||||
{
|
|
||||||
HttpEncoder.entities = new SortedDictionary<string, char>((IComparer<string>) StringComparer.Ordinal);
|
|
||||||
HttpEncoder.entities.Add("nbsp", ' ');
|
|
||||||
HttpEncoder.entities.Add("iexcl", '¡');
|
|
||||||
HttpEncoder.entities.Add("cent", '¢');
|
|
||||||
HttpEncoder.entities.Add("pound", '£');
|
|
||||||
HttpEncoder.entities.Add("curren", '¤');
|
|
||||||
HttpEncoder.entities.Add("yen", '¥');
|
|
||||||
HttpEncoder.entities.Add("brvbar", '¦');
|
|
||||||
HttpEncoder.entities.Add("sect", '§');
|
|
||||||
HttpEncoder.entities.Add("uml", '¨');
|
|
||||||
HttpEncoder.entities.Add("copy", '©');
|
|
||||||
HttpEncoder.entities.Add("ordf", 'ª');
|
|
||||||
HttpEncoder.entities.Add("laquo", '«');
|
|
||||||
HttpEncoder.entities.Add("not", '¬');
|
|
||||||
HttpEncoder.entities.Add("shy", '\u00AD');
|
|
||||||
HttpEncoder.entities.Add("reg", '®');
|
|
||||||
HttpEncoder.entities.Add("macr", '¯');
|
|
||||||
HttpEncoder.entities.Add("deg", '°');
|
|
||||||
HttpEncoder.entities.Add("plusmn", '±');
|
|
||||||
HttpEncoder.entities.Add("sup2", '\u00B2');
|
|
||||||
HttpEncoder.entities.Add("sup3", '\u00B3');
|
|
||||||
HttpEncoder.entities.Add("acute", '´');
|
|
||||||
HttpEncoder.entities.Add("micro", 'µ');
|
|
||||||
HttpEncoder.entities.Add("para", '¶');
|
|
||||||
HttpEncoder.entities.Add("middot", '·');
|
|
||||||
HttpEncoder.entities.Add("cedil", '¸');
|
|
||||||
HttpEncoder.entities.Add("sup1", '\u00B9');
|
|
||||||
HttpEncoder.entities.Add("ordm", 'º');
|
|
||||||
HttpEncoder.entities.Add("raquo", '»');
|
|
||||||
HttpEncoder.entities.Add("frac14", '\u00BC');
|
|
||||||
HttpEncoder.entities.Add("frac12", '\u00BD');
|
|
||||||
HttpEncoder.entities.Add("frac34", '\u00BE');
|
|
||||||
HttpEncoder.entities.Add("iquest", '¿');
|
|
||||||
HttpEncoder.entities.Add("Agrave", 'À');
|
|
||||||
HttpEncoder.entities.Add("Aacute", 'Á');
|
|
||||||
HttpEncoder.entities.Add("Acirc", 'Â');
|
|
||||||
HttpEncoder.entities.Add("Atilde", 'Ã');
|
|
||||||
HttpEncoder.entities.Add("Auml", 'Ä');
|
|
||||||
HttpEncoder.entities.Add("Aring", 'Å');
|
|
||||||
HttpEncoder.entities.Add("AElig", 'Æ');
|
|
||||||
HttpEncoder.entities.Add("Ccedil", 'Ç');
|
|
||||||
HttpEncoder.entities.Add("Egrave", 'È');
|
|
||||||
HttpEncoder.entities.Add("Eacute", 'É');
|
|
||||||
HttpEncoder.entities.Add("Ecirc", 'Ê');
|
|
||||||
HttpEncoder.entities.Add("Euml", 'Ë');
|
|
||||||
HttpEncoder.entities.Add("Igrave", 'Ì');
|
|
||||||
HttpEncoder.entities.Add("Iacute", 'Í');
|
|
||||||
HttpEncoder.entities.Add("Icirc", 'Î');
|
|
||||||
HttpEncoder.entities.Add("Iuml", 'Ï');
|
|
||||||
HttpEncoder.entities.Add("ETH", 'Ð');
|
|
||||||
HttpEncoder.entities.Add("Ntilde", 'Ñ');
|
|
||||||
HttpEncoder.entities.Add("Ograve", 'Ò');
|
|
||||||
HttpEncoder.entities.Add("Oacute", 'Ó');
|
|
||||||
HttpEncoder.entities.Add("Ocirc", 'Ô');
|
|
||||||
HttpEncoder.entities.Add("Otilde", 'Õ');
|
|
||||||
HttpEncoder.entities.Add("Ouml", 'Ö');
|
|
||||||
HttpEncoder.entities.Add("times", '×');
|
|
||||||
HttpEncoder.entities.Add("Oslash", 'Ø');
|
|
||||||
HttpEncoder.entities.Add("Ugrave", 'Ù');
|
|
||||||
HttpEncoder.entities.Add("Uacute", 'Ú');
|
|
||||||
HttpEncoder.entities.Add("Ucirc", 'Û');
|
|
||||||
HttpEncoder.entities.Add("Uuml", 'Ü');
|
|
||||||
HttpEncoder.entities.Add("Yacute", 'Ý');
|
|
||||||
HttpEncoder.entities.Add("THORN", 'Þ');
|
|
||||||
HttpEncoder.entities.Add("szlig", 'ß');
|
|
||||||
HttpEncoder.entities.Add("agrave", 'à');
|
|
||||||
HttpEncoder.entities.Add("aacute", 'á');
|
|
||||||
HttpEncoder.entities.Add("acirc", 'â');
|
|
||||||
HttpEncoder.entities.Add("atilde", 'ã');
|
|
||||||
HttpEncoder.entities.Add("auml", 'ä');
|
|
||||||
HttpEncoder.entities.Add("aring", 'å');
|
|
||||||
HttpEncoder.entities.Add("aelig", 'æ');
|
|
||||||
HttpEncoder.entities.Add("ccedil", 'ç');
|
|
||||||
HttpEncoder.entities.Add("egrave", 'è');
|
|
||||||
HttpEncoder.entities.Add("eacute", 'é');
|
|
||||||
HttpEncoder.entities.Add("ecirc", 'ê');
|
|
||||||
HttpEncoder.entities.Add("euml", 'ë');
|
|
||||||
HttpEncoder.entities.Add("igrave", 'ì');
|
|
||||||
HttpEncoder.entities.Add("iacute", 'í');
|
|
||||||
HttpEncoder.entities.Add("icirc", 'î');
|
|
||||||
HttpEncoder.entities.Add("iuml", 'ï');
|
|
||||||
HttpEncoder.entities.Add("eth", 'ð');
|
|
||||||
HttpEncoder.entities.Add("ntilde", 'ñ');
|
|
||||||
HttpEncoder.entities.Add("ograve", 'ò');
|
|
||||||
HttpEncoder.entities.Add("oacute", 'ó');
|
|
||||||
HttpEncoder.entities.Add("ocirc", 'ô');
|
|
||||||
HttpEncoder.entities.Add("otilde", 'õ');
|
|
||||||
HttpEncoder.entities.Add("ouml", 'ö');
|
|
||||||
HttpEncoder.entities.Add("divide", '÷');
|
|
||||||
HttpEncoder.entities.Add("oslash", 'ø');
|
|
||||||
HttpEncoder.entities.Add("ugrave", 'ù');
|
|
||||||
HttpEncoder.entities.Add("uacute", 'ú');
|
|
||||||
HttpEncoder.entities.Add("ucirc", 'û');
|
|
||||||
HttpEncoder.entities.Add("uuml", 'ü');
|
|
||||||
HttpEncoder.entities.Add("yacute", 'ý');
|
|
||||||
HttpEncoder.entities.Add("thorn", 'þ');
|
|
||||||
HttpEncoder.entities.Add("yuml", 'ÿ');
|
|
||||||
HttpEncoder.entities.Add("fnof", 'ƒ');
|
|
||||||
HttpEncoder.entities.Add("Alpha", 'Α');
|
|
||||||
HttpEncoder.entities.Add("Beta", 'Β');
|
|
||||||
HttpEncoder.entities.Add("Gamma", 'Γ');
|
|
||||||
HttpEncoder.entities.Add("Delta", 'Δ');
|
|
||||||
HttpEncoder.entities.Add("Epsilon", 'Ε');
|
|
||||||
HttpEncoder.entities.Add("Zeta", 'Ζ');
|
|
||||||
HttpEncoder.entities.Add("Eta", 'Η');
|
|
||||||
HttpEncoder.entities.Add("Theta", 'Θ');
|
|
||||||
HttpEncoder.entities.Add("Iota", 'Ι');
|
|
||||||
HttpEncoder.entities.Add("Kappa", 'Κ');
|
|
||||||
HttpEncoder.entities.Add("Lambda", 'Λ');
|
|
||||||
HttpEncoder.entities.Add("Mu", 'Μ');
|
|
||||||
HttpEncoder.entities.Add("Nu", 'Ν');
|
|
||||||
HttpEncoder.entities.Add("Xi", 'Ξ');
|
|
||||||
HttpEncoder.entities.Add("Omicron", 'Ο');
|
|
||||||
HttpEncoder.entities.Add("Pi", 'Π');
|
|
||||||
HttpEncoder.entities.Add("Rho", 'Ρ');
|
|
||||||
HttpEncoder.entities.Add("Sigma", 'Σ');
|
|
||||||
HttpEncoder.entities.Add("Tau", 'Τ');
|
|
||||||
HttpEncoder.entities.Add("Upsilon", 'Υ');
|
|
||||||
HttpEncoder.entities.Add("Phi", 'Φ');
|
|
||||||
HttpEncoder.entities.Add("Chi", 'Χ');
|
|
||||||
HttpEncoder.entities.Add("Psi", 'Ψ');
|
|
||||||
HttpEncoder.entities.Add("Omega", 'Ω');
|
|
||||||
HttpEncoder.entities.Add("alpha", 'α');
|
|
||||||
HttpEncoder.entities.Add("beta", 'β');
|
|
||||||
HttpEncoder.entities.Add("gamma", 'γ');
|
|
||||||
HttpEncoder.entities.Add("delta", 'δ');
|
|
||||||
HttpEncoder.entities.Add("epsilon", 'ε');
|
|
||||||
HttpEncoder.entities.Add("zeta", 'ζ');
|
|
||||||
HttpEncoder.entities.Add("eta", 'η');
|
|
||||||
HttpEncoder.entities.Add("theta", 'θ');
|
|
||||||
HttpEncoder.entities.Add("iota", 'ι');
|
|
||||||
HttpEncoder.entities.Add("kappa", 'κ');
|
|
||||||
HttpEncoder.entities.Add("lambda", 'λ');
|
|
||||||
HttpEncoder.entities.Add("mu", 'μ');
|
|
||||||
HttpEncoder.entities.Add("nu", 'ν');
|
|
||||||
HttpEncoder.entities.Add("xi", 'ξ');
|
|
||||||
HttpEncoder.entities.Add("omicron", 'ο');
|
|
||||||
HttpEncoder.entities.Add("pi", 'π');
|
|
||||||
HttpEncoder.entities.Add("rho", 'ρ');
|
|
||||||
HttpEncoder.entities.Add("sigmaf", 'ς');
|
|
||||||
HttpEncoder.entities.Add("sigma", 'σ');
|
|
||||||
HttpEncoder.entities.Add("tau", 'τ');
|
|
||||||
HttpEncoder.entities.Add("upsilon", 'υ');
|
|
||||||
HttpEncoder.entities.Add("phi", 'φ');
|
|
||||||
HttpEncoder.entities.Add("chi", 'χ');
|
|
||||||
HttpEncoder.entities.Add("psi", 'ψ');
|
|
||||||
HttpEncoder.entities.Add("omega", 'ω');
|
|
||||||
HttpEncoder.entities.Add("thetasym", 'ϑ');
|
|
||||||
HttpEncoder.entities.Add("upsih", 'ϒ');
|
|
||||||
HttpEncoder.entities.Add("piv", 'ϖ');
|
|
||||||
HttpEncoder.entities.Add("bull", '•');
|
|
||||||
HttpEncoder.entities.Add("hellip", '…');
|
|
||||||
HttpEncoder.entities.Add("prime", '′');
|
|
||||||
HttpEncoder.entities.Add("Prime", '″');
|
|
||||||
HttpEncoder.entities.Add("oline", '‾');
|
|
||||||
HttpEncoder.entities.Add("frasl", '⁄');
|
|
||||||
HttpEncoder.entities.Add("weierp", '℘');
|
|
||||||
HttpEncoder.entities.Add("image", 'ℑ');
|
|
||||||
HttpEncoder.entities.Add("real", 'ℜ');
|
|
||||||
HttpEncoder.entities.Add("trade", '™');
|
|
||||||
HttpEncoder.entities.Add("alefsym", 'ℵ');
|
|
||||||
HttpEncoder.entities.Add("larr", '←');
|
|
||||||
HttpEncoder.entities.Add("uarr", '↑');
|
|
||||||
HttpEncoder.entities.Add("rarr", '→');
|
|
||||||
HttpEncoder.entities.Add("darr", '↓');
|
|
||||||
HttpEncoder.entities.Add("harr", '↔');
|
|
||||||
HttpEncoder.entities.Add("crarr", '↵');
|
|
||||||
HttpEncoder.entities.Add("lArr", '⇐');
|
|
||||||
HttpEncoder.entities.Add("uArr", '⇑');
|
|
||||||
HttpEncoder.entities.Add("rArr", '⇒');
|
|
||||||
HttpEncoder.entities.Add("dArr", '⇓');
|
|
||||||
HttpEncoder.entities.Add("hArr", '⇔');
|
|
||||||
HttpEncoder.entities.Add("forall", '∀');
|
|
||||||
HttpEncoder.entities.Add("part", '∂');
|
|
||||||
HttpEncoder.entities.Add("exist", '∃');
|
|
||||||
HttpEncoder.entities.Add("empty", '∅');
|
|
||||||
HttpEncoder.entities.Add("nabla", '∇');
|
|
||||||
HttpEncoder.entities.Add("isin", '∈');
|
|
||||||
HttpEncoder.entities.Add("notin", '∉');
|
|
||||||
HttpEncoder.entities.Add("ni", '∋');
|
|
||||||
HttpEncoder.entities.Add("prod", '∏');
|
|
||||||
HttpEncoder.entities.Add("sum", '∑');
|
|
||||||
HttpEncoder.entities.Add("minus", '−');
|
|
||||||
HttpEncoder.entities.Add("lowast", '∗');
|
|
||||||
HttpEncoder.entities.Add("radic", '√');
|
|
||||||
HttpEncoder.entities.Add("prop", '∝');
|
|
||||||
HttpEncoder.entities.Add("infin", '∞');
|
|
||||||
HttpEncoder.entities.Add("ang", '∠');
|
|
||||||
HttpEncoder.entities.Add("and", '∧');
|
|
||||||
HttpEncoder.entities.Add("or", '∨');
|
|
||||||
HttpEncoder.entities.Add("cap", '∩');
|
|
||||||
HttpEncoder.entities.Add("cup", '∪');
|
|
||||||
HttpEncoder.entities.Add("int", '∫');
|
|
||||||
HttpEncoder.entities.Add("there4", '∴');
|
|
||||||
HttpEncoder.entities.Add("sim", '∼');
|
|
||||||
HttpEncoder.entities.Add("cong", '≅');
|
|
||||||
HttpEncoder.entities.Add("asymp", '≈');
|
|
||||||
HttpEncoder.entities.Add("ne", '≠');
|
|
||||||
HttpEncoder.entities.Add("equiv", '≡');
|
|
||||||
HttpEncoder.entities.Add("le", '≤');
|
|
||||||
HttpEncoder.entities.Add("ge", '≥');
|
|
||||||
HttpEncoder.entities.Add("sub", '⊂');
|
|
||||||
HttpEncoder.entities.Add("sup", '⊃');
|
|
||||||
HttpEncoder.entities.Add("nsub", '⊄');
|
|
||||||
HttpEncoder.entities.Add("sube", '⊆');
|
|
||||||
HttpEncoder.entities.Add("supe", '⊇');
|
|
||||||
HttpEncoder.entities.Add("oplus", '⊕');
|
|
||||||
HttpEncoder.entities.Add("otimes", '⊗');
|
|
||||||
HttpEncoder.entities.Add("perp", '⊥');
|
|
||||||
HttpEncoder.entities.Add("sdot", '⋅');
|
|
||||||
HttpEncoder.entities.Add("lceil", '⌈');
|
|
||||||
HttpEncoder.entities.Add("rceil", '⌉');
|
|
||||||
HttpEncoder.entities.Add("lfloor", '⌊');
|
|
||||||
HttpEncoder.entities.Add("rfloor", '⌋');
|
|
||||||
HttpEncoder.entities.Add("lang", '〈');
|
|
||||||
HttpEncoder.entities.Add("rang", '〉');
|
|
||||||
HttpEncoder.entities.Add("loz", '◊');
|
|
||||||
HttpEncoder.entities.Add("spades", '♠');
|
|
||||||
HttpEncoder.entities.Add("clubs", '♣');
|
|
||||||
HttpEncoder.entities.Add("hearts", '♥');
|
|
||||||
HttpEncoder.entities.Add("diams", '♦');
|
|
||||||
HttpEncoder.entities.Add("quot", '"');
|
|
||||||
HttpEncoder.entities.Add("amp", '&');
|
|
||||||
HttpEncoder.entities.Add("lt", '<');
|
|
||||||
HttpEncoder.entities.Add("gt", '>');
|
|
||||||
HttpEncoder.entities.Add("OElig", 'Œ');
|
|
||||||
HttpEncoder.entities.Add("oelig", 'œ');
|
|
||||||
HttpEncoder.entities.Add("Scaron", 'Š');
|
|
||||||
HttpEncoder.entities.Add("scaron", 'š');
|
|
||||||
HttpEncoder.entities.Add("Yuml", 'Ÿ');
|
|
||||||
HttpEncoder.entities.Add("circ", 'ˆ');
|
|
||||||
HttpEncoder.entities.Add("tilde", '˜');
|
|
||||||
HttpEncoder.entities.Add("ensp", ' ');
|
|
||||||
HttpEncoder.entities.Add("emsp", ' ');
|
|
||||||
HttpEncoder.entities.Add("thinsp", ' ');
|
|
||||||
HttpEncoder.entities.Add("zwnj", '\u200C');
|
|
||||||
HttpEncoder.entities.Add("zwj", '\u200D');
|
|
||||||
HttpEncoder.entities.Add("lrm", '\u200E');
|
|
||||||
HttpEncoder.entities.Add("rlm", '\u200F');
|
|
||||||
HttpEncoder.entities.Add("ndash", '–');
|
|
||||||
HttpEncoder.entities.Add("mdash", '—');
|
|
||||||
HttpEncoder.entities.Add("lsquo", '‘');
|
|
||||||
HttpEncoder.entities.Add("rsquo", '’');
|
|
||||||
HttpEncoder.entities.Add("sbquo", '‚');
|
|
||||||
HttpEncoder.entities.Add("ldquo", '“');
|
|
||||||
HttpEncoder.entities.Add("rdquo", '”');
|
|
||||||
HttpEncoder.entities.Add("bdquo", '„');
|
|
||||||
HttpEncoder.entities.Add("dagger", '†');
|
|
||||||
HttpEncoder.entities.Add("Dagger", '‡');
|
|
||||||
HttpEncoder.entities.Add("permil", '‰');
|
|
||||||
HttpEncoder.entities.Add("lsaquo", '‹');
|
|
||||||
HttpEncoder.entities.Add("rsaquo", '›');
|
|
||||||
HttpEncoder.entities.Add("euro", '€');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3c9f699c227f48e381db521abe59c2e1
|
|
||||||
timeCreated: 1701789490
|
|
@ -1,230 +0,0 @@
|
|||||||
// MIRROR CHANGE: drop in Codice.Utils HttpUtility subset to not depend on Unity's plastic scm package
|
|
||||||
// SOURCE: Unity Plastic SCM package
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Edgegap.Codice.Utils // MIRROR CHANGE: namespace Edgegap.* to not collide if anyone has Plastic SCM installed already
|
|
||||||
{
|
|
||||||
public sealed class HttpUtility
|
|
||||||
{
|
|
||||||
private static void WriteCharBytes(IList buf, char ch, Encoding e)
|
|
||||||
{
|
|
||||||
if (ch > 'ÿ')
|
|
||||||
{
|
|
||||||
Encoding encoding = e;
|
|
||||||
char[] chars = new char[1]{ ch };
|
|
||||||
foreach (byte num in encoding.GetBytes(chars))
|
|
||||||
buf.Add((object) num);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
buf.Add((object) (byte) ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string UrlDecode(string s, Encoding e)
|
|
||||||
{
|
|
||||||
if (null == s)
|
|
||||||
return (string) null;
|
|
||||||
if (s.IndexOf('%') == -1 && s.IndexOf('+') == -1)
|
|
||||||
return s;
|
|
||||||
if (e == null)
|
|
||||||
e = Encoding.UTF8;
|
|
||||||
long length = (long) s.Length;
|
|
||||||
List<byte> buf = new List<byte>();
|
|
||||||
for (int index = 0; (long) index < length; ++index)
|
|
||||||
{
|
|
||||||
char ch = s[index];
|
|
||||||
if (ch == '%' && (long) (index + 2) < length && s[index + 1] != '%')
|
|
||||||
{
|
|
||||||
if (s[index + 1] == 'u' && (long) (index + 5) < length)
|
|
||||||
{
|
|
||||||
int num = HttpUtility.GetChar(s, index + 2, 4);
|
|
||||||
if (num != -1)
|
|
||||||
{
|
|
||||||
HttpUtility.WriteCharBytes((IList) buf, (char) num, e);
|
|
||||||
index += 5;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
HttpUtility.WriteCharBytes((IList) buf, '%', e);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int num;
|
|
||||||
if ((num = HttpUtility.GetChar(s, index + 1, 2)) != -1)
|
|
||||||
{
|
|
||||||
HttpUtility.WriteCharBytes((IList) buf, (char) num, e);
|
|
||||||
index += 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
HttpUtility.WriteCharBytes((IList) buf, '%', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ch == '+')
|
|
||||||
HttpUtility.WriteCharBytes((IList) buf, ' ', e);
|
|
||||||
else
|
|
||||||
HttpUtility.WriteCharBytes((IList) buf, ch, e);
|
|
||||||
}
|
|
||||||
byte[] array = buf.ToArray();
|
|
||||||
return e.GetString(array);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GetInt(byte b)
|
|
||||||
{
|
|
||||||
char ch = (char) b;
|
|
||||||
if (ch >= '0' && ch <= '9')
|
|
||||||
return (int) ch - 48;
|
|
||||||
if (ch >= 'a' && ch <= 'f')
|
|
||||||
return (int) ch - 97 + 10;
|
|
||||||
return ch >= 'A' && ch <= 'F' ? (int) ch - 65 + 10 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GetChar(string str, int offset, int length)
|
|
||||||
{
|
|
||||||
int num1 = 0;
|
|
||||||
int num2 = length + offset;
|
|
||||||
for (int index = offset; index < num2; ++index)
|
|
||||||
{
|
|
||||||
char b = str[index];
|
|
||||||
if (b > '\u007F')
|
|
||||||
return -1;
|
|
||||||
int num3 = HttpUtility.GetInt((byte) b);
|
|
||||||
if (num3 == -1)
|
|
||||||
return -1;
|
|
||||||
num1 = (num1 << 4) + num3;
|
|
||||||
}
|
|
||||||
return num1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string UrlEncode(string str) => HttpUtility.UrlEncode(str, Encoding.UTF8);
|
|
||||||
|
|
||||||
public static string UrlEncode(string s, Encoding Enc)
|
|
||||||
{
|
|
||||||
if (s == null)
|
|
||||||
return (string) null;
|
|
||||||
if (s == string.Empty)
|
|
||||||
return string.Empty;
|
|
||||||
bool flag = false;
|
|
||||||
int length = s.Length;
|
|
||||||
for (int index = 0; index < length; ++index)
|
|
||||||
{
|
|
||||||
char c = s[index];
|
|
||||||
if ((c < '0' || c < 'A' && c > '9' || c > 'Z' && c < 'a' || c > 'z') && !HttpEncoder.NotEncoded(c))
|
|
||||||
{
|
|
||||||
flag = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!flag)
|
|
||||||
return s;
|
|
||||||
byte[] bytes1 = new byte[Enc.GetMaxByteCount(s.Length)];
|
|
||||||
int bytes2 = Enc.GetBytes(s, 0, s.Length, bytes1, 0);
|
|
||||||
return Encoding.ASCII.GetString(HttpUtility.UrlEncodeToBytes(bytes1, 0, bytes2));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] UrlEncodeToBytes(byte[] bytes, int offset, int count) => bytes == null ? (byte[]) null : HttpEncoder.Current.UrlEncode(bytes, offset, count);
|
|
||||||
|
|
||||||
public static string HtmlDecode(string s)
|
|
||||||
{
|
|
||||||
if (s == null)
|
|
||||||
return (string) null;
|
|
||||||
using (StringWriter output = new StringWriter())
|
|
||||||
{
|
|
||||||
HttpEncoder.Current.HtmlDecode(s, (TextWriter) output);
|
|
||||||
return output.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NameValueCollection ParseQueryString(string query) => HttpUtility.ParseQueryString(query, Encoding.UTF8);
|
|
||||||
|
|
||||||
public static NameValueCollection ParseQueryString(
|
|
||||||
string query,
|
|
||||||
Encoding encoding)
|
|
||||||
{
|
|
||||||
if (query == null)
|
|
||||||
throw new ArgumentNullException(nameof (query));
|
|
||||||
if (encoding == null)
|
|
||||||
throw new ArgumentNullException(nameof (encoding));
|
|
||||||
if (query.Length == 0 || query.Length == 1 && query[0] == '?')
|
|
||||||
return (NameValueCollection) new HttpUtility.HttpQSCollection();
|
|
||||||
if (query[0] == '?')
|
|
||||||
query = query.Substring(1);
|
|
||||||
NameValueCollection result = (NameValueCollection) new HttpUtility.HttpQSCollection();
|
|
||||||
HttpUtility.ParseQueryString(query, encoding, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void ParseQueryString(
|
|
||||||
string query,
|
|
||||||
Encoding encoding,
|
|
||||||
NameValueCollection result)
|
|
||||||
{
|
|
||||||
if (query.Length == 0)
|
|
||||||
return;
|
|
||||||
string str1 = HttpUtility.HtmlDecode(query);
|
|
||||||
int length = str1.Length;
|
|
||||||
int num1 = 0;
|
|
||||||
bool flag = true;
|
|
||||||
while (num1 <= length)
|
|
||||||
{
|
|
||||||
int startIndex = -1;
|
|
||||||
int num2 = -1;
|
|
||||||
for (int index = num1; index < length; ++index)
|
|
||||||
{
|
|
||||||
if (startIndex == -1 && str1[index] == '=')
|
|
||||||
startIndex = index + 1;
|
|
||||||
else if (str1[index] == '&')
|
|
||||||
{
|
|
||||||
num2 = index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
flag = false;
|
|
||||||
if (str1[num1] == '?')
|
|
||||||
++num1;
|
|
||||||
}
|
|
||||||
string name;
|
|
||||||
if (startIndex == -1)
|
|
||||||
{
|
|
||||||
name = (string) null;
|
|
||||||
startIndex = num1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
name = HttpUtility.UrlDecode(str1.Substring(num1, startIndex - num1 - 1), encoding);
|
|
||||||
if (num2 < 0)
|
|
||||||
{
|
|
||||||
num1 = -1;
|
|
||||||
num2 = str1.Length;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
num1 = num2 + 1;
|
|
||||||
string str2 = HttpUtility.UrlDecode(str1.Substring(startIndex, num2 - startIndex), encoding);
|
|
||||||
result.Add(name, str2);
|
|
||||||
if (num1 == -1)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class HttpQSCollection : NameValueCollection
|
|
||||||
{
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
int count = this.Count;
|
|
||||||
if (count == 0)
|
|
||||||
return "";
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
|
||||||
string[] allKeys = this.AllKeys;
|
|
||||||
for (int index = 0; index < count; ++index)
|
|
||||||
stringBuilder.AppendFormat("{0}={1}&", (object) allKeys[index], (object) HttpUtility.UrlEncode(this[allKeys[index]]));
|
|
||||||
if (stringBuilder.Length > 0)
|
|
||||||
--stringBuilder.Length;
|
|
||||||
return stringBuilder.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 6f83f468a8b546fd92606db56038f9e6
|
|
||||||
timeCreated: 1701785025
|
|
@ -1,16 +0,0 @@
|
|||||||
FROM ubuntu:bionic
|
|
||||||
|
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
|
||||||
|
|
||||||
COPY Builds/EdgegapServer /root/build/
|
|
||||||
|
|
||||||
WORKDIR /root/
|
|
||||||
|
|
||||||
RUN chmod +x /root/build/ServerBuild
|
|
||||||
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y ca-certificates && \
|
|
||||||
apt-get clean && \
|
|
||||||
update-ca-certificates
|
|
||||||
|
|
||||||
ENTRYPOINT [ "/root/build/ServerBuild", "-batchmode", "-nographics"]
|
|
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 78b80371aabba1d48aac39ec7ccfe7c5
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Edgegap",
|
|
||||||
"rootNamespace": "",
|
|
||||||
"references": [],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [
|
|
||||||
{
|
|
||||||
"name": "com.unity.nuget.newtonsoft-json",
|
|
||||||
"expression": "",
|
|
||||||
"define": "NEWTONSOFT_JSON"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"noEngineReferences": false
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 58ff3a2ca929d114eaf0ca373ff1e07a
|
|
||||||
AssemblyDefinitionImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 635b395f47dc9f742b4d71144921bb0d
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 6d2a4589d6738cb4b82bb1ceebd1453f
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,280 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
// using Codice.Utils; // MIRROR CHANGE
|
|
||||||
using Edgegap.Codice.Utils; // MIRROR CHANGE
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Handles base URL and common methods for all Edgegap APIs.
|
|
||||||
/// </summary>
|
|
||||||
public abstract class EdgegapApiBase
|
|
||||||
{
|
|
||||||
#region Vars
|
|
||||||
private readonly HttpClient _httpClient = new HttpClient(); // Base address set // MIRROR CHANGE: Unity 2020 support
|
|
||||||
protected ApiEnvironment SelectedApiEnvironment { get; }
|
|
||||||
protected EdgegapWindowMetadata.LogLevel LogLevel { get; set; }
|
|
||||||
protected bool IsLogLevelDebug => LogLevel == EdgegapWindowMetadata.LogLevel.Debug;
|
|
||||||
|
|
||||||
/// <summary>Based on SelectedApiEnvironment.</summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
private string GetBaseUrl() =>
|
|
||||||
SelectedApiEnvironment == ApiEnvironment.Staging
|
|
||||||
? ApiEnvironment.Staging.GetApiUrl()
|
|
||||||
: ApiEnvironment.Console.GetApiUrl();
|
|
||||||
#endregion // Vars
|
|
||||||
|
|
||||||
|
|
||||||
/// <param name="apiEnvironment">"console" || "staging-console"?</param>
|
|
||||||
/// <param name="apiToken">Without the "token " prefix, although we'll clear this if present</param>
|
|
||||||
/// <param name="logLevel">You may want more-verbose logs other than errs</param>
|
|
||||||
protected EdgegapApiBase(
|
|
||||||
ApiEnvironment apiEnvironment,
|
|
||||||
string apiToken,
|
|
||||||
EdgegapWindowMetadata.LogLevel logLevel = EdgegapWindowMetadata.LogLevel.Error)
|
|
||||||
{
|
|
||||||
this.SelectedApiEnvironment = apiEnvironment;
|
|
||||||
|
|
||||||
this._httpClient.BaseAddress = new Uri($"{GetBaseUrl()}/");
|
|
||||||
this._httpClient.DefaultRequestHeaders.Accept.Add(
|
|
||||||
new MediaTypeWithQualityHeaderValue("application/json"));
|
|
||||||
|
|
||||||
string cleanedApiToken = apiToken.Replace("token ", ""); // We already prefixed token below
|
|
||||||
this._httpClient.DefaultRequestHeaders.Authorization =
|
|
||||||
new AuthenticationHeaderValue("token", cleanedApiToken);
|
|
||||||
|
|
||||||
this.LogLevel = logLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#region HTTP Requests
|
|
||||||
/// <summary>
|
|
||||||
/// POST | We already added "https://api.edgegap.com/" (or similar) BaseAddress via constructor.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="relativePath"></param>
|
|
||||||
/// <param name="json">Serialize to your model via Newtonsoft</param>
|
|
||||||
/// <returns>
|
|
||||||
/// - Success => returns HttpResponseMessage result
|
|
||||||
/// - Error => Catches errs => returns null (no rethrow)
|
|
||||||
/// </returns>
|
|
||||||
protected async Task<HttpResponseMessage> PostAsync(string relativePath = "", string json = "{}")
|
|
||||||
{
|
|
||||||
StringContent stringContent = CreateStringContent(json);
|
|
||||||
Uri uri = new Uri(_httpClient.BaseAddress, relativePath); // Normalize POST uri: Can't end with `/`.
|
|
||||||
|
|
||||||
if (IsLogLevelDebug)
|
|
||||||
Debug.Log($"PostAsync to: `{uri}` with json: `{json}`");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await ExecuteRequestAsync(() => _httpClient.PostAsync(uri, stringContent));
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.LogError($"Error: {e}");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// PATCH | We already added "https://api.edgegap.com/" (or similar) BaseAddress via constructor.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="relativePath"></param>
|
|
||||||
/// <param name="json">Serialize to your model via Newtonsoft</param>
|
|
||||||
/// <returns>
|
|
||||||
/// - Success => returns HttpResponseMessage result
|
|
||||||
/// - Error => Catches errs => returns null (no rethrow)
|
|
||||||
/// </returns>
|
|
||||||
protected async Task<HttpResponseMessage> PatchAsync(string relativePath = "", string json = "{}")
|
|
||||||
{
|
|
||||||
StringContent stringContent = CreateStringContent(json);
|
|
||||||
Uri uri = new Uri(_httpClient.BaseAddress, relativePath); // Normalize PATCH uri: Can't end with `/`.
|
|
||||||
|
|
||||||
if (IsLogLevelDebug)
|
|
||||||
Debug.Log($"PatchAsync to: `{uri}` with json: `{json}`");
|
|
||||||
|
|
||||||
// (!) As of 11/15/2023, .PatchAsync() is "unsupported by Unity" -- so we manually set the verb and SendAsync()
|
|
||||||
// Create the request manually
|
|
||||||
HttpRequestMessage patchRequest = new HttpRequestMessage(new HttpMethod("PATCH"), uri)
|
|
||||||
{
|
|
||||||
Content = stringContent,
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await ExecuteRequestAsync(() => _httpClient.SendAsync(patchRequest));
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.LogError($"Error: {e}");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// GET | We already added "https://api.edgegap.com/" (or similar) BaseAddress via constructor.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="relativePath"></param>
|
|
||||||
/// <param name="customQuery">
|
|
||||||
/// To append to the URL; eg: "foo=0&bar=1"
|
|
||||||
/// (!) First query key should prefix nothing, as shown</param>
|
|
||||||
/// <returns>
|
|
||||||
/// - Success => returns HttpResponseMessage result
|
|
||||||
/// - Error => Catches errs => returns null (no rethrow)
|
|
||||||
/// </returns>
|
|
||||||
protected async Task<HttpResponseMessage> GetAsync(string relativePath = "", string customQuery = "")
|
|
||||||
{
|
|
||||||
string completeRelativeUri = prepareEdgegapUriWithQuery(
|
|
||||||
relativePath,
|
|
||||||
customQuery);
|
|
||||||
|
|
||||||
if (IsLogLevelDebug)
|
|
||||||
Debug.Log($"GetAsync to: `{completeRelativeUri} with customQuery: `{customQuery}`");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await ExecuteRequestAsync(() => _httpClient.GetAsync(completeRelativeUri));
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.LogError($"Error: {e}");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// DELETE | We already added "https://api.edgegap.com/" (or similar) BaseAddress via constructor.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="relativePath"></param>
|
|
||||||
/// <param name="customQuery">
|
|
||||||
/// To append to the URL; eg: "foo=0&bar=1"
|
|
||||||
/// (!) First query key should prefix nothing, as shown</param>
|
|
||||||
/// <returns>
|
|
||||||
/// - Success => returns HttpResponseMessage result
|
|
||||||
/// - Error => Catches errs => returns null (no rethrow)
|
|
||||||
/// </returns>
|
|
||||||
protected async Task<HttpResponseMessage> DeleteAsync(string relativePath = "", string customQuery = "")
|
|
||||||
{
|
|
||||||
string completeRelativeUri = prepareEdgegapUriWithQuery(
|
|
||||||
relativePath,
|
|
||||||
customQuery);
|
|
||||||
|
|
||||||
if (IsLogLevelDebug)
|
|
||||||
Debug.Log($"DeleteAsync to: `{completeRelativeUri} with customQuery: `{customQuery}`");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await ExecuteRequestAsync(() => _httpClient.DeleteAsync(completeRelativeUri));
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.LogError($"Error: {e}");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>POST || GET</summary>
|
|
||||||
/// <param name="requestFunc"></param>
|
|
||||||
/// <param name="cancellationToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private static async Task<HttpResponseMessage> ExecuteRequestAsync(
|
|
||||||
Func<Task<HttpResponseMessage>> requestFunc,
|
|
||||||
CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
response = await requestFunc();
|
|
||||||
}
|
|
||||||
catch (HttpRequestException e)
|
|
||||||
{
|
|
||||||
Debug.LogError($"HttpRequestException: {e.Message}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (TaskCanceledException e)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
Debug.LogError("Task was cancelled by caller.");
|
|
||||||
else
|
|
||||||
Debug.LogError($"TaskCanceledException: Timeout - {e.Message}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (Exception e) // Generic exception handler
|
|
||||||
{
|
|
||||||
Debug.LogError($"Unexpected error occurred: {e.Message}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for a successful status code
|
|
||||||
if (response == null)
|
|
||||||
{
|
|
||||||
Debug.Log("!Success (null response) - returning 500");
|
|
||||||
return CreateUnknown500Err();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
HttpMethod httpMethod = response.RequestMessage.Method;
|
|
||||||
Debug.Log($"!Success: {(short)response.StatusCode} {response.ReasonPhrase} - " +
|
|
||||||
$"{httpMethod} | {response.RequestMessage.RequestUri}` - " +
|
|
||||||
$"{response.Content?.ReadAsStringAsync().Result}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
#endregion // HTTP Requests
|
|
||||||
|
|
||||||
|
|
||||||
#region Utils
|
|
||||||
/// <summary>Creates a UTF-8 encoded application/json + json obj</summary>
|
|
||||||
/// <param name="json">Arbitrary json obj</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private StringContent CreateStringContent(string json = "{}") =>
|
|
||||||
new StringContent(json, Encoding.UTF8, "application/json"); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
|
|
||||||
private static HttpResponseMessage CreateUnknown500Err() =>
|
|
||||||
new HttpResponseMessage(HttpStatusCode.InternalServerError); // 500 - Unknown // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Merges Edgegap-required query params (source) -> merges with custom query -> normalizes.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="relativePath"></param>
|
|
||||||
/// <param name="customQuery"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private string prepareEdgegapUriWithQuery(string relativePath, string customQuery)
|
|
||||||
{
|
|
||||||
// Create UriBuilder using the BaseAddress
|
|
||||||
UriBuilder uriBuilder = new UriBuilder(_httpClient.BaseAddress);
|
|
||||||
|
|
||||||
// Add the relative path to the UriBuilder's path
|
|
||||||
uriBuilder.Path += relativePath;
|
|
||||||
|
|
||||||
// Parse the existing query from the UriBuilder
|
|
||||||
NameValueCollection query = HttpUtility.ParseQueryString(uriBuilder.Query);
|
|
||||||
|
|
||||||
// Add default "source=unity" param
|
|
||||||
query["source"] = "unity";
|
|
||||||
|
|
||||||
// Parse and merge the custom query parameters
|
|
||||||
NameValueCollection customParams = HttpUtility.ParseQueryString(customQuery);
|
|
||||||
foreach (string key in customParams)
|
|
||||||
{
|
|
||||||
query[key] = customParams[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the merged query back to the UriBuilder
|
|
||||||
uriBuilder.Query = query.ToString();
|
|
||||||
|
|
||||||
// Extract the complete relative URI and return it
|
|
||||||
return uriBuilder.Uri.PathAndQuery;
|
|
||||||
}
|
|
||||||
#endregion // Utils
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 50379f30f5137224aa05a5c7b6b5ebba
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,148 +0,0 @@
|
|||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Edgegap.Editor.Api.Models.Requests;
|
|
||||||
using Edgegap.Editor.Api.Models.Results;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Wraps the v1/app API endpoint: Applications Control API.
|
|
||||||
/// - API Doc | https://docs.edgegap.com/api/#tag/Applications
|
|
||||||
/// </summary>
|
|
||||||
public class EdgegapAppApi : EdgegapApiBase
|
|
||||||
{
|
|
||||||
public EdgegapAppApi(
|
|
||||||
ApiEnvironment apiEnvironment,
|
|
||||||
string apiToken,
|
|
||||||
EdgegapWindowMetadata.LogLevel logLevel = EdgegapWindowMetadata.LogLevel.Error)
|
|
||||||
: base(apiEnvironment, apiToken, logLevel)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#region API Methods
|
|
||||||
/// <summary>
|
|
||||||
/// POST to v1/app
|
|
||||||
/// - Create an application that will regroup application versions.
|
|
||||||
/// - API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/application-post
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// Http info with GetCreateAppResult data model
|
|
||||||
/// - Success: 200
|
|
||||||
/// - Fail: 409 (app already exists), 400 (reached limit)
|
|
||||||
/// </returns>
|
|
||||||
public async Task<EdgegapHttpResult<GetCreateAppResult>> CreateApp(CreateAppRequest request)
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await PostAsync("v1/app", request.ToString());
|
|
||||||
EdgegapHttpResult<GetCreateAppResult> result = new EdgegapHttpResult<GetCreateAppResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
|
|
||||||
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
|
||||||
if (!isSuccess)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// GET to v1/app
|
|
||||||
/// - Get an application that will regroup application versions.
|
|
||||||
/// - API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/application-post
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// Http info with GetCreateAppResult data model
|
|
||||||
/// - Success: 200
|
|
||||||
/// </returns>
|
|
||||||
public async Task<EdgegapHttpResult<GetCreateAppResult>> GetApp(string appName)
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await GetAsync($"v1/app/{appName}");
|
|
||||||
EdgegapHttpResult<GetCreateAppResult> result = new EdgegapHttpResult<GetCreateAppResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
|
|
||||||
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
|
||||||
if (!isSuccess)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// PATCH to v1/app/{app_name}/version/{version_name}
|
|
||||||
/// - Update an *existing* application version with new specifications.
|
|
||||||
/// - API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/app-versions-patch
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// Http info with UpdateAppVersionRequest data model
|
|
||||||
/// - Success: 200
|
|
||||||
/// </returns>
|
|
||||||
public async Task<EdgegapHttpResult<UpsertAppVersionResult>> UpdateAppVersion(UpdateAppVersionRequest request)
|
|
||||||
{
|
|
||||||
string relativePath = $"v1/app/{request.AppName}/version/{request.VersionName}";
|
|
||||||
HttpResponseMessage response = await PatchAsync(relativePath, request.ToString());
|
|
||||||
EdgegapHttpResult<UpsertAppVersionResult> result = new EdgegapHttpResult<UpsertAppVersionResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
|
|
||||||
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
|
||||||
if (!isSuccess)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// POST to v1/app/{app_name}/version
|
|
||||||
/// - Create an new application version with new specifications.
|
|
||||||
/// - API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/app-version-post
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// Http info with UpdateAppVersionRequest data model
|
|
||||||
/// - Success: 200 (no result model)
|
|
||||||
/// - Fail: 409 (app already exists), 400 (reached limit)
|
|
||||||
/// </returns>
|
|
||||||
public async Task<EdgegapHttpResult<UpsertAppVersionResult>> CreateAppVersion(CreateAppVersionRequest request)
|
|
||||||
{
|
|
||||||
string relativePath = $"v1/app/{request.AppName}/version";
|
|
||||||
HttpResponseMessage response = await PostAsync(relativePath, request.ToString());
|
|
||||||
EdgegapHttpResult<UpsertAppVersionResult> result = new EdgegapHttpResult<UpsertAppVersionResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
|
|
||||||
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
|
||||||
|
|
||||||
if (!isSuccess)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endregion // API Methods
|
|
||||||
|
|
||||||
|
|
||||||
#region Chained API Methods
|
|
||||||
/// <summary>
|
|
||||||
/// PATCH and/or POST to v1/app/: Upsert an *existing* application version with new specifications.
|
|
||||||
/// - Consumes either 1 or 2 API calls: 1st tries to PATCH, then POST if PATCH fails (!exists).
|
|
||||||
/// - API POST Doc | https://docs.edgegap.com/api/#tag/Applications/operation/app-version-post
|
|
||||||
/// - API PATCH Doc | https://docs.edgegap.com/api/#tag/Applications/operation/app-versions-patch
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// Http info with UpdateAppVersionRequest data model
|
|
||||||
/// - Success: 200 (no result model)
|
|
||||||
/// - Fail: 409 (app already exists), 400 (reached limit)
|
|
||||||
/// </returns>
|
|
||||||
public async Task<EdgegapHttpResult<UpsertAppVersionResult>> UpsertAppVersion(UpdateAppVersionRequest request)
|
|
||||||
{
|
|
||||||
EdgegapHttpResult<UpsertAppVersionResult> result = await UpdateAppVersion(request); // PATCH
|
|
||||||
|
|
||||||
if (result.HasErr)
|
|
||||||
{
|
|
||||||
// Try to create, instead
|
|
||||||
CreateAppVersionRequest createAppVersionRequest = CreateAppVersionRequest.FromUpdateRequest(request);
|
|
||||||
result = await CreateAppVersion(createAppVersionRequest); // POST
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isSuccess = result.StatusCode == HttpStatusCode.OK; // 200
|
|
||||||
|
|
||||||
if (!isSuccess)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endregion // Chained API Methods
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3b0b3b865abe64b49a4000294c4e9593
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,177 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Edgegap.Editor.Api.Models.Requests;
|
|
||||||
using Edgegap.Editor.Api.Models.Results;
|
|
||||||
using UnityEngine.Assertions;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Wraps the v1/[deploy | status | stop] API endpoints: Deployments Control API.
|
|
||||||
/// - API Doc | https://docs.edgegap.com/api/#tag/Deployments
|
|
||||||
/// </summary>
|
|
||||||
public class EdgegapDeploymentsApi : EdgegapApiBase
|
|
||||||
{
|
|
||||||
public EdgegapDeploymentsApi(
|
|
||||||
ApiEnvironment apiEnvironment,
|
|
||||||
string apiToken,
|
|
||||||
EdgegapWindowMetadata.LogLevel logLevel = EdgegapWindowMetadata.LogLevel.Error)
|
|
||||||
: base(apiEnvironment, apiToken, logLevel)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#region API Methods
|
|
||||||
/// <summary>
|
|
||||||
/// POST v1/deploy
|
|
||||||
/// - Create a new deployment. Deployment is a server instance of your application version.
|
|
||||||
/// - API Doc | https://docs.edgegap.com/api/#tag/Deployments
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// Http info with CreateDeploymentResult data model
|
|
||||||
/// - Success: 200
|
|
||||||
/// </returns>
|
|
||||||
public async Task<EdgegapHttpResult<CreateDeploymentResult>> CreateDeploymentAsync(
|
|
||||||
CreateDeploymentRequest request)
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await PostAsync("v1/deploy", request.ToString());
|
|
||||||
EdgegapHttpResult<CreateDeploymentResult> result = new EdgegapHttpResult<CreateDeploymentResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
|
|
||||||
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
|
||||||
if (!isSuccess)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// GET v1/status/{requestId}
|
|
||||||
/// - Retrieve the information for a deployment.
|
|
||||||
/// - API Doc | https://docs.edgegap.com/api/#tag/Deployments/operation/deployment-status-get
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="requestId">
|
|
||||||
/// Unique Identifier to keep track of your request across all Arbitrium ecosystem.
|
|
||||||
/// It's included in the response of the app deploy. Ex: "93924761ccde"</param>
|
|
||||||
/// <returns>
|
|
||||||
/// Http info with GetDeploymentStatusResult data model
|
|
||||||
/// - Success: 200
|
|
||||||
/// </returns>
|
|
||||||
public async Task<EdgegapHttpResult<GetDeploymentStatusResult>> GetDeploymentStatusAsync(string requestId)
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await GetAsync($"v1/status/{requestId}");
|
|
||||||
EdgegapHttpResult<GetDeploymentStatusResult> result = new EdgegapHttpResult<GetDeploymentStatusResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
|
|
||||||
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
|
||||||
if (!isSuccess)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// DELETE v1/stop/{requestId}
|
|
||||||
/// - Delete an instance of deployment. It will stop the running container and all its games.
|
|
||||||
/// - API Doc | https://docs.edgegap.com/api/#tag/Deployments/operation/deployment-status-get
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="requestId">
|
|
||||||
/// Unique Identifier to keep track of your request across all Arbitrium ecosystem.
|
|
||||||
/// It's included in the response of the app deploy. Ex: "93924761ccde"</param>
|
|
||||||
/// <returns>
|
|
||||||
/// Http info with GetDeploymentStatusResult data model
|
|
||||||
/// - Success: 200
|
|
||||||
/// </returns>
|
|
||||||
public async Task<EdgegapHttpResult<StopActiveDeploymentResult>> StopActiveDeploymentAsync(string requestId)
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await DeleteAsync($"v1/stop/{requestId}");
|
|
||||||
EdgegapHttpResult<StopActiveDeploymentResult> result = new EdgegapHttpResult<StopActiveDeploymentResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
|
|
||||||
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
|
||||||
if (!isSuccess)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endregion // API Methods
|
|
||||||
|
|
||||||
|
|
||||||
#region Chained API Methods
|
|
||||||
/// <summary>
|
|
||||||
/// POST v1/deploy => GET v1/status/{requestId}
|
|
||||||
/// - Create a new deployment. Deployment is a server instance of your application version.
|
|
||||||
/// - Then => await READY status.
|
|
||||||
/// - API Doc | https://docs.edgegap.com/api/#tag/Deployments
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// Http info with CreateDeploymentResult data model (with a READY deployment status)
|
|
||||||
/// - Success: 200
|
|
||||||
/// - Error: If createResult.HasErr, returns createResult
|
|
||||||
/// </returns>
|
|
||||||
public async Task<EdgegapHttpResult<CreateDeploymentResult>> CreateDeploymentAwaitReadyStatusAsync(
|
|
||||||
CreateDeploymentRequest request, TimeSpan pollInterval)
|
|
||||||
{
|
|
||||||
EdgegapHttpResult<CreateDeploymentResult> createResponse = await CreateDeploymentAsync(request);
|
|
||||||
|
|
||||||
// Create =>
|
|
||||||
bool isCreateSuccess = createResponse.StatusCode == HttpStatusCode.OK; // 200
|
|
||||||
if (!isCreateSuccess)
|
|
||||||
return createResponse;
|
|
||||||
|
|
||||||
// Await Status READY =>
|
|
||||||
string requestId = createResponse.Data.RequestId;
|
|
||||||
_ = await AwaitReadyStatusAsync(requestId, pollInterval);
|
|
||||||
|
|
||||||
// Return no matter what the result; no need to validate
|
|
||||||
return createResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>If you recently deployed but want to await READY status.</summary>
|
|
||||||
/// <param name="requestId"></param>
|
|
||||||
/// <param name="pollInterval"></param>
|
|
||||||
public async Task<EdgegapHttpResult<GetDeploymentStatusResult>> AwaitReadyStatusAsync(
|
|
||||||
string requestId,
|
|
||||||
TimeSpan pollInterval)
|
|
||||||
{
|
|
||||||
Assert.IsTrue(!string.IsNullOrEmpty(requestId)); // Validate
|
|
||||||
|
|
||||||
EdgegapHttpResult<GetDeploymentStatusResult> statusResponse = null;
|
|
||||||
CancellationTokenSource cts = new CancellationTokenSource (TimeSpan.FromMinutes( // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
EdgegapWindowMetadata.DEPLOYMENT_AWAIT_READY_STATUS_TIMEOUT_MINS));
|
|
||||||
bool isReady = false;
|
|
||||||
|
|
||||||
while (!isReady && !cts.Token.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
await Task.Delay(pollInterval, cts.Token);
|
|
||||||
statusResponse = await GetDeploymentStatusAsync(requestId);
|
|
||||||
isReady = statusResponse.Data.CurrentStatus == EdgegapWindowMetadata.READY_STATUS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return statusResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>If you recently stopped a deployment, but want to await TERMINATED (410) status.</summary>
|
|
||||||
/// <param name="requestId"></param>
|
|
||||||
/// <param name="pollInterval"></param>
|
|
||||||
public async Task<EdgegapHttpResult<StopActiveDeploymentResult>> AwaitTerminatedDeleteStatusAsync(
|
|
||||||
string requestId,
|
|
||||||
TimeSpan pollInterval)
|
|
||||||
{
|
|
||||||
EdgegapHttpResult<StopActiveDeploymentResult> deleteResponse = null;
|
|
||||||
CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromMinutes( // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
EdgegapWindowMetadata.DEPLOYMENT_AWAIT_READY_STATUS_TIMEOUT_MINS));
|
|
||||||
bool isStopped = false;
|
|
||||||
|
|
||||||
while (!isStopped && !cts.Token.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
await Task.Delay(pollInterval, cts.Token);
|
|
||||||
deleteResponse = await StopActiveDeploymentAsync(requestId);
|
|
||||||
isStopped = deleteResponse.StatusCode == HttpStatusCode.Gone; // 410
|
|
||||||
}
|
|
||||||
|
|
||||||
return deleteResponse;
|
|
||||||
}
|
|
||||||
#endregion Chained API Methods
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 37ecdc6abda4402419438f2284ef2d95
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,47 +0,0 @@
|
|||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Edgegap.Editor.Api.Models.Results;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Wraps the v1/ip API endpoint: "IP Lookup" API.
|
|
||||||
/// - API Doc | https://docs.edgegap.com/api/#tag/IP-Lookup
|
|
||||||
/// </summary>
|
|
||||||
public class EdgegapIpApi : EdgegapApiBase
|
|
||||||
{
|
|
||||||
public EdgegapIpApi(
|
|
||||||
ApiEnvironment apiEnvironment,
|
|
||||||
string apiToken,
|
|
||||||
EdgegapWindowMetadata.LogLevel logLevel = EdgegapWindowMetadata.LogLevel.Error)
|
|
||||||
: base(apiEnvironment, apiToken, logLevel)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#region API Methods
|
|
||||||
/// <summary>
|
|
||||||
/// GET to v1/app
|
|
||||||
/// - Retrieve your public IP address.
|
|
||||||
/// - API Doc | https://docs.edgegap.com/api/#tag/IP-Lookup/operation/IP
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// Http info with GetCreateAppResult data model
|
|
||||||
/// - Success: 200
|
|
||||||
/// - Fail: 409 (app already exists), 400 (reached limit)
|
|
||||||
/// </returns>
|
|
||||||
public async Task<EdgegapHttpResult<GetYourPublicIpResult>> GetYourPublicIp()
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await GetAsync("v1/ip");
|
|
||||||
EdgegapHttpResult<GetYourPublicIpResult> result = new EdgegapHttpResult<GetYourPublicIpResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
|
|
||||||
bool isSuccess = response.StatusCode == HttpStatusCode.OK; // 200
|
|
||||||
if (!isSuccess)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endregion // API Methods
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: fac4a7425623f39488af09d60549313e
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,52 +0,0 @@
|
|||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Edgegap.Editor.Api.Models.Results;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api
|
|
||||||
{
|
|
||||||
/// <summary>Wraps the v1/wizard API endpoint. Used for internal purposes.</summary>
|
|
||||||
public class EdgegapWizardApi : EdgegapApiBase
|
|
||||||
{
|
|
||||||
/// <summary>Extended path after the base uri</summary>
|
|
||||||
public EdgegapWizardApi(
|
|
||||||
ApiEnvironment apiEnvironment,
|
|
||||||
string apiToken,
|
|
||||||
EdgegapWindowMetadata.LogLevel logLevel = EdgegapWindowMetadata.LogLevel.Error)
|
|
||||||
: base(apiEnvironment, apiToken, logLevel)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#region API Methods
|
|
||||||
/// <summary>POST to v1/wizard/init-quick-start</summary>
|
|
||||||
/// <returns>
|
|
||||||
/// Http info with no explicit data model
|
|
||||||
/// - Success: 204 (no result model)
|
|
||||||
/// </returns>
|
|
||||||
public async Task<EdgegapHttpResult> InitQuickStart()
|
|
||||||
{
|
|
||||||
string json = new JObject { ["source"] = "unity" }.ToString();
|
|
||||||
HttpResponseMessage response = await PostAsync("v1/wizard/init-quick-start", json);
|
|
||||||
EdgegapHttpResult result = new EdgegapHttpResult(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>GET to v1/wizard/registry-credentials</summary>
|
|
||||||
/// <returns>
|
|
||||||
/// - Http info with GetRegistryCredentialsResult data model
|
|
||||||
/// - Success: 200
|
|
||||||
/// - Error: Likely if called before a successful InitQuickStart(),
|
|
||||||
/// or if called in a staging env. Soon, this will be available in production.
|
|
||||||
/// </returns>
|
|
||||||
public async Task<EdgegapHttpResult<GetRegistryCredentialsResult>> GetRegistryCredentials()
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await GetAsync("v1/wizard/registry-credentials");
|
|
||||||
EdgegapHttpResult<GetRegistryCredentialsResult> result = new EdgegapHttpResult<GetRegistryCredentialsResult>(response); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endregion // API Methods
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f6986ee67361f0b45928ccd70c7ab12c
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: aed107c714fce71449ef56590221c567
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,28 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Used in `UpdateAppVersionRequest`, `CreateAppVersionRequest`.
|
|
||||||
/// For GetDeploymentStatusResult, see DeploymentPortsData
|
|
||||||
/// </summary>
|
|
||||||
public class AppPortsData
|
|
||||||
{
|
|
||||||
/// <summary>1024~49151; Default 7770</summary>
|
|
||||||
[JsonProperty("port")]
|
|
||||||
public int Port { get; set; } = EdgegapWindowMetadata.PORT_DEFAULT;
|
|
||||||
|
|
||||||
/// <summary>Default "UDP"</summary>
|
|
||||||
[JsonProperty("protocol")]
|
|
||||||
public string ProtocolStr { get; set; } = EdgegapWindowMetadata.DEFAULT_PROTOCOL_TYPE.ToString();
|
|
||||||
|
|
||||||
[JsonProperty("to_check")]
|
|
||||||
public bool ToCheck { get; set; } = true;
|
|
||||||
|
|
||||||
[JsonProperty("tls_upgrade")]
|
|
||||||
public bool TlsUpgrade { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("name")]
|
|
||||||
public string PortName { get; set; } = "Game Port";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b6d4864ea3706574fb35920c6fab46fa
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,29 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models
|
|
||||||
{
|
|
||||||
/// <summary>Used in `GetDeploymentStatus`.</summary>
|
|
||||||
public class DeploymentPortsData
|
|
||||||
{
|
|
||||||
[JsonProperty("external")]
|
|
||||||
public int External { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("internal")]
|
|
||||||
public int Internal { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("protocol")]
|
|
||||||
public string Protocol { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("name")]
|
|
||||||
public string PortName { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("tls_upgrade")]
|
|
||||||
public bool TlsUpgrade { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("link")]
|
|
||||||
public string Link { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("proxy")]
|
|
||||||
public int? Proxy { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 62d51b44b8414c9f968ca607ccb06b7e
|
|
||||||
timeCreated: 1701522748
|
|
@ -1,28 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models
|
|
||||||
{
|
|
||||||
public class LocationData
|
|
||||||
{
|
|
||||||
[JsonProperty("city")]
|
|
||||||
public string City { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("country")]
|
|
||||||
public string Country { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("continent")]
|
|
||||||
public string Continent { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("administrative_division")]
|
|
||||||
public string AdministrativeDivision { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("timezone")]
|
|
||||||
public string Timezone { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("latitude")]
|
|
||||||
public double Latitude { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("longitude")]
|
|
||||||
public double Longitude { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 57eed0dbd556e074c992cf6599a1f6bd
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,18 +0,0 @@
|
|||||||
namespace Edgegap.Editor.Api.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Unity default: UDP.
|
|
||||||
/// (!) UDP !works in WebGL.
|
|
||||||
/// </summary>
|
|
||||||
public enum ProtocolType
|
|
||||||
{
|
|
||||||
/// <summary>Unity default - fastest; !works in WebGL.</summary>
|
|
||||||
UDP,
|
|
||||||
|
|
||||||
/// <summary>Slower, but more reliable; works in WebGL.</summary>
|
|
||||||
TCP,
|
|
||||||
|
|
||||||
/// <summary>Slower, but more reliable; works in WebGL.</summary>
|
|
||||||
WS,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: be5acd63e783b364ebdbb783639e2d32
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d1b2a5c481353934f906c30ba047df9b
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,55 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models.Requests
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Request model for https://docs.edgegap.com/api/#tag/Applications/operation/application-post
|
|
||||||
/// </summary>
|
|
||||||
public class CreateAppRequest
|
|
||||||
{
|
|
||||||
#region Required
|
|
||||||
/// <summary>*The application name.</summary>
|
|
||||||
[JsonProperty("name")]
|
|
||||||
public string AppName { get; set; }
|
|
||||||
#endregion // Required
|
|
||||||
|
|
||||||
|
|
||||||
#region Optional
|
|
||||||
/// <summary>*If the application can be deployed.</summary>
|
|
||||||
[JsonProperty("is_active")]
|
|
||||||
public bool IsActive { get; set; }
|
|
||||||
|
|
||||||
/// <summary>*Image base64 string.</summary>
|
|
||||||
[JsonProperty("image")]
|
|
||||||
public string Image { get; set; }
|
|
||||||
|
|
||||||
/// <summary>If the telemetry agent is installed on the versions of this app.</summary>
|
|
||||||
[JsonProperty("is_telemetry_agent_active")]
|
|
||||||
public bool IsTelemetryAgentActive { get; set; }
|
|
||||||
#endregion // Optional
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>Used by Newtonsoft</summary>
|
|
||||||
public CreateAppRequest()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Init with required info</summary>
|
|
||||||
/// <param name="appName">The application name</param>
|
|
||||||
/// <param name="isActive">If the application can be deployed</param>
|
|
||||||
/// <param name="image">Image base64 string</param>
|
|
||||||
public CreateAppRequest(
|
|
||||||
string appName,
|
|
||||||
bool isActive,
|
|
||||||
string image)
|
|
||||||
{
|
|
||||||
this.AppName = appName;
|
|
||||||
this.IsActive = isActive;
|
|
||||||
this.Image = image;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Parse to json str</summary>
|
|
||||||
public override string ToString() =>
|
|
||||||
JsonConvert.SerializeObject(this);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 0a492d7c515b8894ea30b37db6b7efe4
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,225 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models.Requests
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Request model for `POST v1/app/{app_name}/version`.
|
|
||||||
/// API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/app-version-post
|
|
||||||
/// </summary>
|
|
||||||
public class CreateAppVersionRequest
|
|
||||||
{
|
|
||||||
#region Required
|
|
||||||
/// <summary>*The name of the application associated.</summary>
|
|
||||||
[JsonIgnore] // *Path var
|
|
||||||
public string AppName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>*The name of the application associated.</summary>
|
|
||||||
[JsonProperty("name")]
|
|
||||||
public string VersionName { get; set; } = EdgegapWindowMetadata.DEFAULT_VERSION_TAG;
|
|
||||||
|
|
||||||
/// <summary>*The tag of your image. Default == "latest".</summary>
|
|
||||||
/// <example>"0.1.2" || "latest" (although "latest" !recommended; use actual versions in production)</example>
|
|
||||||
[JsonProperty("docker_tag")]
|
|
||||||
public string DockerTag { get; set; } = EdgegapWindowMetadata.DEFAULT_VERSION_TAG;
|
|
||||||
|
|
||||||
/// <summary>*The name of your image.</summary>
|
|
||||||
/// <example>"edgegap/demo" || "myCompany-someId/mylowercaseapp"</example>
|
|
||||||
[JsonProperty("docker_image")]
|
|
||||||
public string DockerImage { get; set; } = "";
|
|
||||||
|
|
||||||
/// <summary>*The Repository where the image is.</summary>
|
|
||||||
/// <example>"registry.edgegap.com" || "harbor.edgegap.com" || "docker.io"</example>
|
|
||||||
[JsonProperty("docker_repository")]
|
|
||||||
public string DockerRepository { get; set; } = "";
|
|
||||||
|
|
||||||
/// <summary>*Units of vCPU needed (1024 = 1vcpu)</summary>
|
|
||||||
[JsonProperty("req_cpu")]
|
|
||||||
public int ReqCpu { get; set; } = 256;
|
|
||||||
|
|
||||||
/// <summary>*Units of memory in MB needed (1024 = 1 GPU)</summary>
|
|
||||||
[JsonProperty("req_memory")]
|
|
||||||
public int ReqMemory { get; set; } = 256;
|
|
||||||
|
|
||||||
/// <summary>*Required: At least 1 { Port, ProtocolStr }.</summary>
|
|
||||||
[JsonProperty("ports")]
|
|
||||||
public AppPortsData[] Ports { get; set; } = {};
|
|
||||||
|
|
||||||
/// <summary>The username to access the docker repository</summary>
|
|
||||||
[JsonProperty("private_username")]
|
|
||||||
public string PrivateUsername { get; set; } = "";
|
|
||||||
|
|
||||||
/// <summary>The Private Password or Token of the username (We recommend to use a token)</summary>
|
|
||||||
[JsonProperty("private_token")]
|
|
||||||
public string PrivateToken { get; set; } = "";
|
|
||||||
#endregion // Required
|
|
||||||
|
|
||||||
|
|
||||||
// #region Optional
|
|
||||||
// [JsonProperty("is_active")]
|
|
||||||
// public bool IsActive { get; set; } = true;
|
|
||||||
//
|
|
||||||
// [JsonProperty("req_video")]
|
|
||||||
// public int ReqVideo { get; set; } = 256;
|
|
||||||
//
|
|
||||||
// [JsonProperty("max_duration")]
|
|
||||||
// public int MaxDuration { get; set; } = 30;
|
|
||||||
//
|
|
||||||
// [JsonProperty("use_telemetry")]
|
|
||||||
// public bool UseTelemetry { get; set; } = true;
|
|
||||||
//
|
|
||||||
// [JsonProperty("inject_context_env")]
|
|
||||||
// public bool InjectContextEnv { get; set; } = true;
|
|
||||||
//
|
|
||||||
// [JsonProperty("whitelisting_active")]
|
|
||||||
// public bool WhitelistingActive { get; set; } = true;
|
|
||||||
//
|
|
||||||
// [JsonProperty("force_cache")]
|
|
||||||
// public bool ForceCache { get; set; }
|
|
||||||
//
|
|
||||||
// [JsonProperty("cache_min_hour")]
|
|
||||||
// public int CacheMinHour { get; set; }
|
|
||||||
//
|
|
||||||
// [JsonProperty("cache_max_hour")]
|
|
||||||
// public int CacheMaxHour { get; set; }
|
|
||||||
//
|
|
||||||
// [JsonProperty("time_to_deploy")]
|
|
||||||
// public int TimeToDeploy { get; set; } = 15;
|
|
||||||
//
|
|
||||||
// [JsonProperty("enable_all_locations")]
|
|
||||||
// public bool EnableAllLocations { get; set; }
|
|
||||||
//
|
|
||||||
// [JsonProperty("termination_grace_period_seconds")]
|
|
||||||
// public int TerminationGracePeriodSeconds { get; set; } = 5;
|
|
||||||
//
|
|
||||||
// [JsonProperty("endpoint_storage")]
|
|
||||||
// public string EndpointStorage { get; set; } = "";
|
|
||||||
//
|
|
||||||
// [JsonProperty("command")]
|
|
||||||
// public string Command { get; set; }
|
|
||||||
//
|
|
||||||
// [JsonProperty("arguments")]
|
|
||||||
// public string Arguments { get; set; }
|
|
||||||
//
|
|
||||||
// [JsonProperty("verify_image")]
|
|
||||||
// public bool VerifyImage { get; set; }
|
|
||||||
//
|
|
||||||
// [JsonProperty("session_config")]
|
|
||||||
// public SessionConfigData SessionConfig { get; set; } = new();
|
|
||||||
//
|
|
||||||
// [JsonProperty("probe")]
|
|
||||||
// public ProbeData Probe { get; set; } = new();
|
|
||||||
//
|
|
||||||
// [JsonProperty("envs")]
|
|
||||||
// public EnvsData[] Envs { get; set; } = {};
|
|
||||||
//
|
|
||||||
// public class SessionConfigData
|
|
||||||
// {
|
|
||||||
// [JsonProperty("kind")]
|
|
||||||
// public string Kind { get; set; } = "Seat";
|
|
||||||
//
|
|
||||||
// [JsonProperty("sockets")]
|
|
||||||
// public int Sockets { get; set; } = 10;
|
|
||||||
//
|
|
||||||
// [JsonProperty("autodeploy")]
|
|
||||||
// public bool Autodeploy { get; set; } = true;
|
|
||||||
//
|
|
||||||
// [JsonProperty("empty_ttl")]
|
|
||||||
// public int EmptyTtl { get; set; } = 60;
|
|
||||||
//
|
|
||||||
// [JsonProperty("session_max_duration")]
|
|
||||||
// public int SessionMaxDuration { get; set; } = 60;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// public class ProbeData
|
|
||||||
// {
|
|
||||||
// [JsonProperty("optimal_ping")]
|
|
||||||
// public int OptimalPing { get; set; } = 60;
|
|
||||||
//
|
|
||||||
// [JsonProperty("rejected_ping")]
|
|
||||||
// public int RejectedPing { get; set; } = 180;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public class EnvsData
|
|
||||||
// {
|
|
||||||
// [JsonProperty("key")]
|
|
||||||
// public string Key { get; set; }
|
|
||||||
//
|
|
||||||
// [JsonProperty("value")]
|
|
||||||
// public string Value { get; set; }
|
|
||||||
//
|
|
||||||
// [JsonProperty("is_secret")]
|
|
||||||
// public bool IsSecret { get; set; } = true;
|
|
||||||
// }
|
|
||||||
// #endregion // Optional
|
|
||||||
|
|
||||||
/// <summary>Used by Newtonsoft</summary>
|
|
||||||
public CreateAppVersionRequest()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Init with required info.
|
|
||||||
/// (!) If looking for refs, also see FromUpdateRequest() builder below.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="appName">The name of the application.</param>
|
|
||||||
/// <param name="containerRegistryUsername"></param>
|
|
||||||
/// <param name="containerRegistryPasswordToken"></param>
|
|
||||||
/// <param name="portNum"></param>
|
|
||||||
/// <param name="protocolType"></param>
|
|
||||||
public CreateAppVersionRequest(
|
|
||||||
string appName,
|
|
||||||
string containerRegistryUsername,
|
|
||||||
string containerRegistryPasswordToken,
|
|
||||||
int portNum,
|
|
||||||
ProtocolType protocolType)
|
|
||||||
{
|
|
||||||
this.AppName = appName;
|
|
||||||
this.PrivateUsername = containerRegistryUsername;
|
|
||||||
this.PrivateToken = containerRegistryPasswordToken;
|
|
||||||
this.Ports = new AppPortsData[]
|
|
||||||
{
|
|
||||||
new AppPortsData() // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
{
|
|
||||||
Port = portNum,
|
|
||||||
ProtocolStr = protocolType.ToString(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Port from Update PATCH model: If you tried to Update, but !exists, you probably want to create it next.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="updateRequest"></param>
|
|
||||||
public static CreateAppVersionRequest FromUpdateRequest(UpdateAppVersionRequest updateRequest)
|
|
||||||
{
|
|
||||||
// Convert the updateRequest to JSON
|
|
||||||
string json = JsonConvert.SerializeObject(updateRequest);
|
|
||||||
|
|
||||||
// Deserialize the JSON back to CreateAppVersionRequest
|
|
||||||
CreateAppVersionRequest createReq = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
createReq = JsonConvert.DeserializeObject<CreateAppVersionRequest>(json);
|
|
||||||
createReq.AppName = updateRequest.AppName; // Normally JsonIgnored in Update
|
|
||||||
createReq.VersionName = updateRequest.VersionName; // Normally JsonIgnored in Update
|
|
||||||
createReq.PrivateUsername = updateRequest.PrivateUsername;
|
|
||||||
createReq.PrivateToken = updateRequest.PrivateToken;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.LogError($"Error (when parsing CreateAppVersionRequest from CreateAppVersionRequest): {e}");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
return createReq;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Parse to json str</summary>
|
|
||||||
public override string ToString() =>
|
|
||||||
JsonConvert.SerializeObject(this);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 0bb645e2f9d04384a85739269cc8a4e1
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,63 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models.Requests
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Request model for `POST v1/deploy`.
|
|
||||||
/// API Doc | https://docs.edgegap.com/api/#tag/Deployments/operation/deploy
|
|
||||||
/// </summary>
|
|
||||||
public class CreateDeploymentRequest
|
|
||||||
{
|
|
||||||
#region Required
|
|
||||||
/// <summary>*Required: The name of the App you want to deploy.</summary>
|
|
||||||
[JsonProperty("app_name")]
|
|
||||||
public string AppName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// *Required: The name of the App Version you want to deploy;
|
|
||||||
/// if not present, the last version created is picked.
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("version_name")]
|
|
||||||
public string VersionName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// *Required: The List of IP of your user.
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("ip_list")]
|
|
||||||
public string[] IpList { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// *Required: The list of IP of your user with their location (latitude, longitude).
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("geo_ip_list")]
|
|
||||||
public string[] GeoIpList { get; set; } = {};
|
|
||||||
#endregion // Required
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>Used by Newtonsoft</summary>
|
|
||||||
public CreateDeploymentRequest()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Init with required info; used for a single external IP address.</summary>
|
|
||||||
/// <param name="appName">The name of the application.</param>
|
|
||||||
/// <param name="versionName">
|
|
||||||
/// The name of the App Version you want to deploy, if not present,
|
|
||||||
/// the last version created is picked.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="externalIp">Obtain from IpApi.</param>
|
|
||||||
public CreateDeploymentRequest(
|
|
||||||
string appName,
|
|
||||||
string versionName,
|
|
||||||
string externalIp)
|
|
||||||
{
|
|
||||||
this.AppName = appName;
|
|
||||||
this.VersionName = versionName;
|
|
||||||
this.IpList = new[] { externalIp };
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Parse to json str</summary>
|
|
||||||
public override string ToString() =>
|
|
||||||
JsonConvert.SerializeObject(this);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: aae7b317093230e419bc0f8be1097ea6
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,175 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models.Requests
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Request model for `PATCH v1/app/{app_name}/version/{version_name}`.
|
|
||||||
/// Request model for https://docs.edgegap.com/api/#tag/Applications/operation/app-versions-patch
|
|
||||||
/// TODO: Split "Create" and "Update" into their own, separate models: CTRL+F for "(!)" for more info.
|
|
||||||
/// </summary>
|
|
||||||
public class UpdateAppVersionRequest
|
|
||||||
{
|
|
||||||
#region Required
|
|
||||||
/// <summary>*Required: The name of the application.</summary>
|
|
||||||
[JsonIgnore] // *Path var
|
|
||||||
public string AppName { get; set; }
|
|
||||||
#endregion // Required
|
|
||||||
|
|
||||||
|
|
||||||
#region Optional
|
|
||||||
/// <summary>The name of the application version.</summary>
|
|
||||||
[JsonIgnore] // *Path var
|
|
||||||
public string VersionName { get; set; } = EdgegapWindowMetadata.DEFAULT_VERSION_TAG;
|
|
||||||
|
|
||||||
/// <summary>At least 1 { Port, ProtocolStr }</summary>
|
|
||||||
[JsonProperty("ports")]
|
|
||||||
public AppPortsData[] Ports { get; set; } = {};
|
|
||||||
|
|
||||||
/// <summary>The Repository where the image is.</summary>
|
|
||||||
/// <example>"registry.edgegap.com" || "harbor.edgegap.com" || "docker.io"</example>
|
|
||||||
[JsonProperty("docker_repository")]
|
|
||||||
public string DockerRepository { get; set; } = "";
|
|
||||||
|
|
||||||
/// <summary>The name of your image.</summary>
|
|
||||||
/// <example>"edgegap/demo" || "myCompany-someId/mylowercaseapp"</example>
|
|
||||||
[JsonProperty("docker_image")]
|
|
||||||
public string DockerImage { get; set; } = "";
|
|
||||||
|
|
||||||
/// <summary>The tag of your image. Default == "latest".</summary>
|
|
||||||
/// <example>"0.1.2" || "latest" (although "latest" !recommended; use actual versions in production)</example>
|
|
||||||
[JsonProperty("docker_tag")]
|
|
||||||
public string DockerTag { get; set; } = EdgegapWindowMetadata.DEFAULT_VERSION_TAG;
|
|
||||||
|
|
||||||
[JsonProperty("is_active")]
|
|
||||||
public bool IsActive { get; set; } = true;
|
|
||||||
|
|
||||||
[JsonProperty("private_username")]
|
|
||||||
public string PrivateUsername { get; set; } = "";
|
|
||||||
|
|
||||||
[JsonProperty("private_token")]
|
|
||||||
public string PrivateToken { get; set; } = "";
|
|
||||||
|
|
||||||
#region (!) Shows in API docs for PATCH, but could be CREATE only? "Unknown Args"
|
|
||||||
// [JsonProperty("req_cpu")]
|
|
||||||
// public int ReqCpu { get; set; } = 256;
|
|
||||||
//
|
|
||||||
// [JsonProperty("req_memory")]
|
|
||||||
// public int ReqMemory { get; set; } = 256;
|
|
||||||
//
|
|
||||||
// [JsonProperty("req_video")]
|
|
||||||
// public int ReqVideo { get; set; } = 256;
|
|
||||||
#endregion // (!) Shows in API docs for PATCH, but could be CREATE only? "Unknown Args"
|
|
||||||
|
|
||||||
[JsonProperty("max_duration")]
|
|
||||||
public int MaxDuration { get; set; } = 60;
|
|
||||||
|
|
||||||
[JsonProperty("use_telemetry")]
|
|
||||||
public bool UseTelemetry { get; set; } = true;
|
|
||||||
|
|
||||||
[JsonProperty("inject_context_env")]
|
|
||||||
public bool InjectContextEnv { get; set; } = true;
|
|
||||||
|
|
||||||
[JsonProperty("whitelisting_active")]
|
|
||||||
public bool WhitelistingActive { get; set; } = false;
|
|
||||||
|
|
||||||
[JsonProperty("force_cache")]
|
|
||||||
public bool ForceCache { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("cache_min_hour")]
|
|
||||||
public int CacheMinHour { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("cache_max_hour")]
|
|
||||||
public int CacheMaxHour { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("time_to_deploy")]
|
|
||||||
public int TimeToDeploy { get; set; } = 120;
|
|
||||||
|
|
||||||
[JsonProperty("enable_all_locations")]
|
|
||||||
public bool EnableAllLocations { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("termination_grace_period_seconds")]
|
|
||||||
public int TerminationGracePeriodSeconds { get; set; } = 5;
|
|
||||||
|
|
||||||
// // (!) BUG: Expects empty string "" at minimum; however, empty string will throw server err
|
|
||||||
// [JsonProperty("endpoint_storage")]
|
|
||||||
// public string EndpointStorage { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("command")]
|
|
||||||
public string Command { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("arguments")]
|
|
||||||
public string Arguments { get; set; }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// (!) Setting this will trigger a very specific type of game that will affect the AppVersion.
|
|
||||||
// /// TODO: Is leaving as null the same as commenting out?
|
|
||||||
// /// </summary>
|
|
||||||
// [JsonProperty("session_config")]
|
|
||||||
// public SessionConfigData SessionConfig { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("probe")]
|
|
||||||
public ProbeData Probe { get; set; } = new ProbeData(); // MIRROR CHANGE: 'new()' not supported in Unity 2020
|
|
||||||
|
|
||||||
[JsonProperty("envs")]
|
|
||||||
public EnvsData[] Envs { get; set; } = {};
|
|
||||||
|
|
||||||
public class SessionConfigData
|
|
||||||
{
|
|
||||||
[JsonProperty("kind")]
|
|
||||||
public string Kind { get; set; } = "Seat";
|
|
||||||
|
|
||||||
[JsonProperty("sockets")]
|
|
||||||
public int Sockets { get; set; } = 10;
|
|
||||||
|
|
||||||
[JsonProperty("autodeploy")]
|
|
||||||
public bool Autodeploy { get; set; } = true;
|
|
||||||
|
|
||||||
[JsonProperty("empty_ttl")]
|
|
||||||
public int EmptyTtl { get; set; } = 60;
|
|
||||||
|
|
||||||
[JsonProperty("session_max_duration")]
|
|
||||||
public int SessionMaxDuration { get; set; } = 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ProbeData
|
|
||||||
{
|
|
||||||
[JsonProperty("optimal_ping")]
|
|
||||||
public int OptimalPing { get; set; } = 60;
|
|
||||||
|
|
||||||
[JsonProperty("rejected_ping")]
|
|
||||||
public int RejectedPing { get; set; } = 180;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class EnvsData
|
|
||||||
{
|
|
||||||
[JsonProperty("key")]
|
|
||||||
public string Key { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("value")]
|
|
||||||
public string Value { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("is_secret")]
|
|
||||||
public bool IsSecret { get; set; } = true;
|
|
||||||
}
|
|
||||||
#endregion // Optional
|
|
||||||
|
|
||||||
/// <summary>Used by Newtonsoft</summary>
|
|
||||||
public UpdateAppVersionRequest()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Init with required info. Default version/tag == "default".
|
|
||||||
/// Since we're updating, we only require the AppName.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="appName">The name of the application.</param>
|
|
||||||
public UpdateAppVersionRequest(string appName)
|
|
||||||
{
|
|
||||||
this.AppName = appName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Parse to json str</summary>
|
|
||||||
public override string ToString() =>
|
|
||||||
JsonConvert.SerializeObject(this);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 8da9712633ee1e64faca0b960d4bed31
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: aa4ceffbc97b8254885a63937def2324
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,53 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models.Results
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Result model for `POST v1/deploy`.
|
|
||||||
/// </summary>
|
|
||||||
public class CreateDeploymentResult
|
|
||||||
{
|
|
||||||
[JsonProperty("request_id")]
|
|
||||||
public string RequestId { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("request_dns")]
|
|
||||||
public string RequestDns { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("request_app")]
|
|
||||||
public string RequestApp { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("request_version")]
|
|
||||||
public string RequestVersion { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("request_user_count")]
|
|
||||||
public int RequestUserCount { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("city")]
|
|
||||||
public string City { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("country")]
|
|
||||||
public string Country { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("continent")]
|
|
||||||
public string Continent { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("administrative_division")]
|
|
||||||
public string AdministrativeDivision { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("tags")]
|
|
||||||
public string[] Tags { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("container_log_storage")]
|
|
||||||
public ContainerLogStorageData ContainerLogStorage { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
public class ContainerLogStorageData
|
|
||||||
{
|
|
||||||
[JsonProperty("enabled")]
|
|
||||||
public bool Enabled { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("endpoint_storage")]
|
|
||||||
public string EndpointStorage { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 8361abc6f84fccd4cba26dc285d335dd
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,12 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models.Results
|
|
||||||
{
|
|
||||||
/// <summary>Edgegap error, generally just containing `message`</summary>
|
|
||||||
public class EdgegapErrorResult
|
|
||||||
{
|
|
||||||
/// <summary>Friendly, UI-facing error message from Edgegap; can be lengthy.</summary>
|
|
||||||
[JsonProperty("message")]
|
|
||||||
public string ErrorMessage { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5b29093cb10cf3040b76f4fbe77a435d
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,118 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models.Results
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Wraps the inner json data with outer http info.
|
|
||||||
/// This class overload contains no json-deserialiable data result.
|
|
||||||
/// </summary>
|
|
||||||
public class EdgegapHttpResult
|
|
||||||
{
|
|
||||||
/// <summary>HTTP Status code for the request.</summary>
|
|
||||||
public HttpStatusCode StatusCode { get; }
|
|
||||||
|
|
||||||
/// <summary>This could be err, success, or null.</summary>
|
|
||||||
public string Json { get; }
|
|
||||||
|
|
||||||
/// <summary>eg: "POST"</summary>
|
|
||||||
public HttpMethod HttpMethod;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Typically is sent by servers together with the status code.
|
|
||||||
/// Useful for fallback err descriptions, often based on the status code.
|
|
||||||
/// </summary>
|
|
||||||
public string ReasonPhrase { get; }
|
|
||||||
|
|
||||||
/// <summary>Contains `message` with friendly info.</summary>
|
|
||||||
public bool HasErr => Error != null;
|
|
||||||
public EdgegapErrorResult Error { get; set; }
|
|
||||||
|
|
||||||
#region Common Shortcuts
|
|
||||||
/// <summary>OK</summary>
|
|
||||||
public bool IsResultCode200 => StatusCode == HttpStatusCode.OK;
|
|
||||||
|
|
||||||
/// <summary>NoContent</summary>
|
|
||||||
public bool IsResultCode204 => StatusCode == HttpStatusCode.NoContent;
|
|
||||||
|
|
||||||
/// <summary>Forbidden</summary>
|
|
||||||
public bool IsResultCode403 => StatusCode == HttpStatusCode.Forbidden;
|
|
||||||
|
|
||||||
/// <summary>Conflict</summary>
|
|
||||||
public bool IsResultCode409 => StatusCode == HttpStatusCode.Conflict;
|
|
||||||
|
|
||||||
/// <summary>BadRequest</summary>
|
|
||||||
public bool IsResultCode400 => StatusCode == HttpStatusCode.BadRequest;
|
|
||||||
|
|
||||||
/// <summary>Gone</summary>
|
|
||||||
public bool IsResultCode410 => StatusCode == HttpStatusCode.Gone;
|
|
||||||
#endregion // Common Shortcuts
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor that initializes the class based on an HttpResponseMessage.
|
|
||||||
/// </summary>
|
|
||||||
public EdgegapHttpResult(HttpResponseMessage httpResponse)
|
|
||||||
{
|
|
||||||
this.ReasonPhrase = httpResponse.ReasonPhrase;
|
|
||||||
this.StatusCode = httpResponse.StatusCode;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// TODO: This can be read async with `await`, but can't do this in a Constructor.
|
|
||||||
// Instead, make a factory builder Task =>
|
|
||||||
this.Json = httpResponse.Content.ReadAsStringAsync().Result;
|
|
||||||
|
|
||||||
this.Error = JsonConvert.DeserializeObject<EdgegapErrorResult>(Json);
|
|
||||||
if (Error != null && string.IsNullOrEmpty(Error.ErrorMessage))
|
|
||||||
Error = null;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.LogError("Error (reading httpResponse.Content): Client expected json, " +
|
|
||||||
$"but server returned !json: {e} - ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Wraps the inner json data with outer http info.
|
|
||||||
/// This class overload contains json-deserialiable data result.
|
|
||||||
/// </summary>
|
|
||||||
public class EdgegapHttpResult<TResult> : EdgegapHttpResult
|
|
||||||
{
|
|
||||||
/// <summary>The actual result model from Json. Could be null!</summary>
|
|
||||||
public TResult Data { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
public EdgegapHttpResult(HttpResponseMessage httpResponse, bool isLogLevelDebug = false)
|
|
||||||
: base(httpResponse)
|
|
||||||
{
|
|
||||||
this.HttpMethod = httpResponse.RequestMessage.Method;
|
|
||||||
|
|
||||||
// Assuming JSON content and using Newtonsoft.Json for deserialization
|
|
||||||
bool isDeserializable = httpResponse.Content != null &&
|
|
||||||
httpResponse.Content.Headers.ContentType.MediaType == "application/json";
|
|
||||||
|
|
||||||
if (isDeserializable)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.Data = JsonConvert.DeserializeObject<TResult>(Json);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.LogError($"Error (deserializing EdgegapHttpResult.Data): {e} - json: {Json}");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLogLevelDebug)
|
|
||||||
UnityEngine.Debug.Log($"{typeof(TResult).Name} result: {JObject.Parse(Json)}"); // Prettified
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 888bfc2c113487b44a3103648d2c2ae3
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,31 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models.Results
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Result model for `[GET | POST] v1/app`.
|
|
||||||
/// POST API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/application-post
|
|
||||||
/// GET API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/application-get
|
|
||||||
/// </summary>
|
|
||||||
public class GetCreateAppResult
|
|
||||||
{
|
|
||||||
[JsonProperty("name")]
|
|
||||||
public string AppName { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("is_active")]
|
|
||||||
public bool IsActive { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Optional</summary>
|
|
||||||
[JsonProperty("is_telemetry_agent_active")]
|
|
||||||
public bool IsTelemetryAgentActive { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("image")]
|
|
||||||
public string Image { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("create_time")]
|
|
||||||
public string CreateTimeStr { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("last_updated")]
|
|
||||||
public string LastUpdatedStr { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: a66c935238edd8846b1e9e9e19cfab70
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,89 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models.Results
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Result model for `GET v1/status/{request_id}`.
|
|
||||||
/// API Doc | https://docs.edgegap.com/api/#tag/Deployments/operation/deployment-status-get
|
|
||||||
/// </summary>
|
|
||||||
public class GetDeploymentStatusResult
|
|
||||||
{
|
|
||||||
[JsonProperty("request_id")]
|
|
||||||
public string RequestId { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("fqdn")]
|
|
||||||
public string Fqdn { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("app_name")]
|
|
||||||
public string AppName { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("app_version")]
|
|
||||||
public string AppVersion { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("current_status")]
|
|
||||||
public string CurrentStatus { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("running")]
|
|
||||||
public bool Running { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("whitelisting_active")]
|
|
||||||
public bool WhitelistingActive { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("start_time")]
|
|
||||||
public string StartTime { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("removal_time")]
|
|
||||||
public string RemovalTime { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("elapsed_time")]
|
|
||||||
public int? ElapsedTime { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("last_status")]
|
|
||||||
public string LastStatus { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("error")]
|
|
||||||
public bool Error { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("error_detail")]
|
|
||||||
public string ErrorDetail { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("public_ip")]
|
|
||||||
public string PublicIp { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("sessions")]
|
|
||||||
public SessionData[] Sessions { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("location")]
|
|
||||||
public LocationData Location { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("tags")]
|
|
||||||
public string[] Tags { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("sockets")]
|
|
||||||
public string Sockets { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("sockets_usage")]
|
|
||||||
public string SocketsUsage { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("command")]
|
|
||||||
public string Command { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("arguments")]
|
|
||||||
public string Arguments { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// TODO: Server should swap `ports` to an array of DeploymentPortsData (instead of an object of dynamic unknown objects).
|
|
||||||
/// <example>
|
|
||||||
/// {
|
|
||||||
/// "7777", {}
|
|
||||||
/// },
|
|
||||||
/// {
|
|
||||||
/// "Some Port Name", {}
|
|
||||||
/// }
|
|
||||||
/// </example>
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("ports")]
|
|
||||||
public Dictionary<string, DeploymentPortsData> PortsDict { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: c658b7f5c5d5d0648934b0ae1d71de9a
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,22 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models.Results
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Result model for `GET v1/wizard/registry-credentials`.
|
|
||||||
/// </summary>
|
|
||||||
public class GetRegistryCredentialsResult
|
|
||||||
{
|
|
||||||
[JsonProperty("registry_url")]
|
|
||||||
public string RegistryUrl { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("project")]
|
|
||||||
public string Project { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("username")]
|
|
||||||
public string Username { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("token")]
|
|
||||||
public string Token { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 8e6af130c329d2b43b2f4b0dc8639477
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,14 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models.Results
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Result model for `GET v1/ip`.
|
|
||||||
/// GET API Doc | https://docs.edgegap.com/api/#tag/IP-Lookup/operation/IP
|
|
||||||
/// </summary>
|
|
||||||
public class GetYourPublicIpResult
|
|
||||||
{
|
|
||||||
[JsonProperty("public_ip")]
|
|
||||||
public string PublicIp { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 73c9651ef0fdfcb449ec0120016963a0
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,89 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models.Results
|
|
||||||
{
|
|
||||||
public class StopActiveDeploymentResult
|
|
||||||
{
|
|
||||||
[JsonProperty("message")]
|
|
||||||
public string Message { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("deployment_summary")]
|
|
||||||
public DeploymentSummaryData DeploymentSummary { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
public class DeploymentSummaryData
|
|
||||||
{
|
|
||||||
[JsonProperty("request_id")]
|
|
||||||
public string RequestId { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("fqdn")]
|
|
||||||
public string Fqdn { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("app_name")]
|
|
||||||
public string AppName { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("app_version")]
|
|
||||||
public string AppVersion { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("current_status")]
|
|
||||||
public string CurrentStatus { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("running")]
|
|
||||||
public bool Running { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("whitelisting_active")]
|
|
||||||
public bool WhitelistingActive { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("start_time")]
|
|
||||||
public string StartTime { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("removal_time")]
|
|
||||||
public string RemovalTime { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("elapsed_time")]
|
|
||||||
public int ElapsedTime { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("last_status")]
|
|
||||||
public string LastStatus { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("error")]
|
|
||||||
public bool Error { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("error_detail")]
|
|
||||||
public string ErrorDetail { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("ports")]
|
|
||||||
public PortsData Ports { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("public_ip")]
|
|
||||||
public string PublicIp { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("sessions")]
|
|
||||||
public SessionData[] Sessions { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("location")]
|
|
||||||
public LocationData Location { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("tags")]
|
|
||||||
public string[] Tags { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("sockets")]
|
|
||||||
public string Sockets { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("sockets_usage")]
|
|
||||||
public string SocketsUsage { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("command")]
|
|
||||||
public string Command { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("arguments")]
|
|
||||||
public string Arguments { get; set; }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PortsData
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 9e2e4d9424ca8f7459803e631acf912f
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,165 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models.Results
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Result model for:
|
|
||||||
/// - `POST 1/app/{app_name}/version`
|
|
||||||
/// - `PATCH v1/app/{app_name}/version/{version_name}`
|
|
||||||
/// POST API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/application-post
|
|
||||||
/// PATCH API Doc | https://docs.edgegap.com/api/#tag/Applications/operation/app-versions-patch
|
|
||||||
/// </summary>
|
|
||||||
public class UpsertAppVersionResult
|
|
||||||
{
|
|
||||||
[JsonProperty("success")]
|
|
||||||
public bool Success { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("version")]
|
|
||||||
public VersionData Version { get; set; }
|
|
||||||
|
|
||||||
public class VersionData
|
|
||||||
{
|
|
||||||
[JsonProperty("name")]
|
|
||||||
public string VersionName { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("is_active")]
|
|
||||||
public bool IsActive { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("docker_repository")]
|
|
||||||
public string DockerRepository { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("docker_image")]
|
|
||||||
public string DockerImage { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("docker_tag")]
|
|
||||||
public string DockerTag { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("private_username")]
|
|
||||||
public string PrivateUsername { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("private_token")]
|
|
||||||
public string PrivateToken { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("req_cpu")]
|
|
||||||
public int? ReqCpu { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("req_memory")]
|
|
||||||
public int? ReqMemory { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("req_video")]
|
|
||||||
public int? ReqVideo { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("max_duration")]
|
|
||||||
public int? MaxDuration { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("use_telemetry")]
|
|
||||||
public bool UseTelemetry { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("inject_context_env")]
|
|
||||||
public bool InjectContextEnv { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("whitelisting_active")]
|
|
||||||
public bool WhitelistingActive { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("force_cache")]
|
|
||||||
public bool ForceCache { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("cache_min_hour")]
|
|
||||||
public int? CacheMinHour { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("cache_max_hour")]
|
|
||||||
public int? CacheMaxHour { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("time_to_deploy")]
|
|
||||||
public int? TimeToDeploy { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("enable_all_locations")]
|
|
||||||
public bool EnableAllLocations { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("session_config")]
|
|
||||||
public SessionConfigData SessionConfig { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("ports")]
|
|
||||||
public PortsData[] Ports { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("probe")]
|
|
||||||
public ProbeData Probe { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("envs")]
|
|
||||||
public EnvsData[] Envs { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("verify_image")]
|
|
||||||
public bool VerifyImage { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("termination_grace_period_seconds")]
|
|
||||||
public int? TerminationGracePeriodSeconds { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("endpoint_storage")]
|
|
||||||
public string EndpointStorage { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("command")]
|
|
||||||
public string Command { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("arguments")]
|
|
||||||
public string Arguments { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SessionConfigData
|
|
||||||
{
|
|
||||||
[JsonProperty("kind")]
|
|
||||||
public string Kind { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("sockets")]
|
|
||||||
public int? Sockets { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("autodeploy")]
|
|
||||||
public bool Autodeploy { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("empty_ttl")]
|
|
||||||
public int? EmptyTtl { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("session_max_duration")]
|
|
||||||
public int? SessionMaxDuration { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PortsData
|
|
||||||
{
|
|
||||||
[JsonProperty("port")]
|
|
||||||
public int? Port { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("protocol")]
|
|
||||||
public string Protocol { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("to_check")]
|
|
||||||
public bool ToCheck { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("tls_upgrade")]
|
|
||||||
public bool TlsUpgrade { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("name")]
|
|
||||||
public string PortName { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ProbeData
|
|
||||||
{
|
|
||||||
[JsonProperty("optimal_ping")]
|
|
||||||
public int? OptimalPing { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("rejected_ping")]
|
|
||||||
public int? RejectedPing { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class EnvsData
|
|
||||||
{
|
|
||||||
[JsonProperty("key")]
|
|
||||||
public string Key { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("value")]
|
|
||||||
public string Value { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("is_secret")]
|
|
||||||
public bool IsSecret { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: a7dde7d59c66d8c44b86af35e853f9f5
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,28 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor.Api.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Shared model for `GetDeploymentStatusResult`, `StopActiveDeploymentResult`.
|
|
||||||
/// </summary>
|
|
||||||
public class SessionData
|
|
||||||
{
|
|
||||||
[JsonProperty("session_id")]
|
|
||||||
public string SessionId { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("status")]
|
|
||||||
public string Status { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("ready")]
|
|
||||||
public bool Ready { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("linked")]
|
|
||||||
public bool Linked { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("kind")]
|
|
||||||
public string Kind { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("user_count")]
|
|
||||||
public string UserCount { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5f9024e4ca5438e4788e461387313531
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,37 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine.UIElements;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor
|
|
||||||
{
|
|
||||||
/// <summary>Slightly shake a UI button to indicate attention.</summary>
|
|
||||||
public class ButtonShaker
|
|
||||||
{
|
|
||||||
const string SHAKE_START_CLASS = "shakeStart";
|
|
||||||
const string SHAKE_STOP_CLASS = "shakeEnd";
|
|
||||||
private Button targetButton;
|
|
||||||
|
|
||||||
public ButtonShaker(Button buttonToShake) =>
|
|
||||||
targetButton = buttonToShake;
|
|
||||||
|
|
||||||
/// <summary>Shake the button x times for x msDelayBetweenShakes each.
|
|
||||||
/// 1 shake = 1 bigger -> followed by 1 smaller.</summary>
|
|
||||||
/// <param name="msDelayBetweenShakes"></param>
|
|
||||||
/// <param name="iterations"># of shakes</param>
|
|
||||||
public async Task ApplyShakeAsync(int msDelayBetweenShakes = 40, int iterations = 2)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < iterations; i++)
|
|
||||||
await shakeOnce(msDelayBetweenShakes);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task shakeOnce(int msDelayBetweenShakes)
|
|
||||||
{
|
|
||||||
targetButton.AddToClassList(SHAKE_START_CLASS);
|
|
||||||
await Task.Delay(msDelayBetweenShakes); // duration of the first transition
|
|
||||||
targetButton.RemoveFromClassList(SHAKE_START_CLASS);
|
|
||||||
|
|
||||||
targetButton.AddToClassList(SHAKE_STOP_CLASS);
|
|
||||||
await Task.Delay(msDelayBetweenShakes); // duration of the second transition
|
|
||||||
targetButton.RemoveFromClassList(SHAKE_STOP_CLASS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f963d64ffcf32ba4bba54fe1cd70b5a1
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,307 +0,0 @@
|
|||||||
#if UNITY_EDITOR
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.Build.Reporting;
|
|
||||||
|
|
||||||
using Debug = UnityEngine.Debug;
|
|
||||||
|
|
||||||
namespace Edgegap
|
|
||||||
{
|
|
||||||
internal static class EdgegapBuildUtils
|
|
||||||
{
|
|
||||||
public static bool IsArmCPU() =>
|
|
||||||
RuntimeInformation.ProcessArchitecture == Architecture.Arm ||
|
|
||||||
RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
|
|
||||||
|
|
||||||
public static BuildReport BuildServer()
|
|
||||||
{
|
|
||||||
IEnumerable<string> scenes = EditorBuildSettings.scenes
|
|
||||||
.Where(s => s.enabled)
|
|
||||||
.Select(s => s.path);
|
|
||||||
BuildPlayerOptions options = new BuildPlayerOptions
|
|
||||||
{
|
|
||||||
scenes = scenes.ToArray(),
|
|
||||||
target = BuildTarget.StandaloneLinux64,
|
|
||||||
// MIRROR CHANGE
|
|
||||||
#if UNITY_2021_3_OR_NEWER
|
|
||||||
subtarget = (int)StandaloneBuildSubtarget.Server, // dedicated server with UNITY_SERVER define
|
|
||||||
#else
|
|
||||||
options = BuildOptions.EnableHeadlessMode, // obsolete and missing UNITY_SERVER define
|
|
||||||
#endif
|
|
||||||
// END MIRROR CHANGE
|
|
||||||
locationPathName = "Builds/EdgegapServer/ServerBuild"
|
|
||||||
};
|
|
||||||
|
|
||||||
return BuildPipeline.BuildPlayer(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<bool> DockerSetupAndInstallationCheck()
|
|
||||||
{
|
|
||||||
if (!File.Exists("Dockerfile"))
|
|
||||||
{
|
|
||||||
File.WriteAllText("Dockerfile", dockerFileText);
|
|
||||||
}
|
|
||||||
|
|
||||||
string output = null;
|
|
||||||
string error = null;
|
|
||||||
await RunCommand_DockerVersion(msg => output = msg, msg => error = msg); // MIRROR CHANGE
|
|
||||||
if (!string.IsNullOrEmpty(error))
|
|
||||||
{
|
|
||||||
Debug.LogError(error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Debug.Log($"[Edgegap] Docker version detected: {output}"); // MIRROR CHANGE
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// MIRROR CHANGE
|
|
||||||
static async Task RunCommand_DockerVersion(Action<string> outputReciever = null, Action<string> errorReciever = null)
|
|
||||||
{
|
|
||||||
#if UNITY_EDITOR_WIN
|
|
||||||
await RunCommand("cmd.exe", "/c docker --version", outputReciever, errorReciever);
|
|
||||||
#elif UNITY_EDITOR_OSX
|
|
||||||
await RunCommand("/bin/bash", "-c \"docker --version\"", outputReciever, errorReciever);
|
|
||||||
#elif UNITY_EDITOR_LINUX
|
|
||||||
await RunCommand("/bin/bash", "-c \"docker --version\"", outputReciever, errorReciever);
|
|
||||||
#else
|
|
||||||
Debug.LogError("The platform is not supported yet.");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// MIRROR CHANGE
|
|
||||||
public static async Task RunCommand_DockerBuild(string registry, string imageRepo, string tag, Action<string> onStatusUpdate)
|
|
||||||
{
|
|
||||||
string realErrorMessage = null;
|
|
||||||
|
|
||||||
// ARM -> x86 support:
|
|
||||||
// build commands use 'buildx' on ARM cpus for cross compilation.
|
|
||||||
// otherwise docker builds would not launch when deployed because
|
|
||||||
// Edgegap's infrastructure is on x86. instead the deployment logs
|
|
||||||
// would show an error in a linux .go file with 'not found'.
|
|
||||||
string buildCommand = IsArmCPU() ? "buildx build --platform linux/amd64" : "build";
|
|
||||||
|
|
||||||
#if UNITY_EDITOR_WIN
|
|
||||||
await RunCommand("docker.exe", $"{buildCommand} -t {registry}/{imageRepo}:{tag} .", onStatusUpdate,
|
|
||||||
#elif UNITY_EDITOR_OSX
|
|
||||||
await RunCommand("/bin/bash", $"-c \"docker {buildCommand} -t {registry}/{imageRepo}:{tag} .\"", onStatusUpdate,
|
|
||||||
#elif UNITY_EDITOR_LINUX
|
|
||||||
await RunCommand("/bin/bash", $"-c \"docker {buildCommand} -t {registry}/{imageRepo}:{tag} .\"", onStatusUpdate,
|
|
||||||
#endif
|
|
||||||
(msg) =>
|
|
||||||
{
|
|
||||||
if (msg.Contains("ERROR"))
|
|
||||||
{
|
|
||||||
realErrorMessage = msg;
|
|
||||||
}
|
|
||||||
onStatusUpdate(msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
if(realErrorMessage != null)
|
|
||||||
{
|
|
||||||
throw new Exception(realErrorMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<(bool, string)> RunCommand_DockerPush(string registry, string imageRepo, string tag, Action<string> onStatusUpdate)
|
|
||||||
{
|
|
||||||
string error = string.Empty;
|
|
||||||
#if UNITY_EDITOR_WIN
|
|
||||||
await RunCommand("docker.exe", $"push {registry}/{imageRepo}:{tag}", onStatusUpdate, (msg) => error += msg + "\n");
|
|
||||||
#elif UNITY_EDITOR_OSX
|
|
||||||
await RunCommand("/bin/bash", $"-c \"docker push {registry}/{imageRepo}:{tag}\"", onStatusUpdate, (msg) => error += msg + "\n");
|
|
||||||
#elif UNITY_EDITOR_LINUX
|
|
||||||
await RunCommand("/bin/bash", $"-c \"docker push {registry}/{imageRepo}:{tag}\"", onStatusUpdate, (msg) => error += msg + "\n");
|
|
||||||
#endif
|
|
||||||
if (!string.IsNullOrEmpty(error))
|
|
||||||
{
|
|
||||||
Debug.LogError(error);
|
|
||||||
return (false, error);
|
|
||||||
}
|
|
||||||
return (true, null);
|
|
||||||
}
|
|
||||||
// END MIRROR CHANGE
|
|
||||||
|
|
||||||
static async Task RunCommand(string command, string arguments, Action<string> outputReciever = null, Action<string> errorReciever = null)
|
|
||||||
{
|
|
||||||
ProcessStartInfo startInfo = new ProcessStartInfo()
|
|
||||||
{
|
|
||||||
FileName = command,
|
|
||||||
Arguments = arguments,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true,
|
|
||||||
UseShellExecute = false,
|
|
||||||
CreateNoWindow = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
// MIRROR CHANGE
|
|
||||||
#if !UNITY_EDITOR_WIN
|
|
||||||
// on mac, commands like 'docker' aren't found because it's not in the application's PATH
|
|
||||||
// even if it runs on mac's terminal.
|
|
||||||
// to solve this we need to do two steps:
|
|
||||||
// 1. add /usr/bin/local to PATH if it's not there already. often this is missing in the application.
|
|
||||||
// this is where docker is usually instaled.
|
|
||||||
// 2. add PATH to ProcessStartInfo
|
|
||||||
string existingPath = Environment.GetEnvironmentVariable("PATH");
|
|
||||||
string customPath = $"{existingPath}:/usr/local/bin";
|
|
||||||
startInfo.EnvironmentVariables["PATH"] = customPath;
|
|
||||||
// Debug.Log("PATH: " + customPath);
|
|
||||||
#endif
|
|
||||||
// END MIRROR CHANGE
|
|
||||||
|
|
||||||
Process proc = new Process() { StartInfo = startInfo, };
|
|
||||||
proc.EnableRaisingEvents = true;
|
|
||||||
|
|
||||||
ConcurrentQueue<string> errors = new ConcurrentQueue<string>();
|
|
||||||
ConcurrentQueue<string> outputs = new ConcurrentQueue<string>();
|
|
||||||
|
|
||||||
void pipeQueue(ConcurrentQueue<string> q, Action<string> opt)
|
|
||||||
{
|
|
||||||
while (!q.IsEmpty)
|
|
||||||
{
|
|
||||||
if (q.TryDequeue(out string msg) && !string.IsNullOrWhiteSpace(msg))
|
|
||||||
{
|
|
||||||
opt?.Invoke(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proc.OutputDataReceived += (s, e) => outputs.Enqueue(e.Data);
|
|
||||||
proc.ErrorDataReceived += (s, e) => errors.Enqueue(e.Data);
|
|
||||||
|
|
||||||
proc.Start();
|
|
||||||
proc.BeginOutputReadLine();
|
|
||||||
proc.BeginErrorReadLine();
|
|
||||||
|
|
||||||
while (!proc.HasExited)
|
|
||||||
{
|
|
||||||
await Task.Delay(100);
|
|
||||||
pipeQueue(errors, errorReciever);
|
|
||||||
pipeQueue(outputs, outputReciever);
|
|
||||||
}
|
|
||||||
|
|
||||||
pipeQueue(errors, errorReciever);
|
|
||||||
pipeQueue(outputs, outputReciever);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
static Regex lastDigitsRegex = new Regex("([0-9])+$");
|
|
||||||
|
|
||||||
public static string IncrementTag(string tag)
|
|
||||||
{
|
|
||||||
Match lastDigits = lastDigitsRegex.Match(tag);
|
|
||||||
if (!lastDigits.Success)
|
|
||||||
{
|
|
||||||
return tag + " _1";
|
|
||||||
}
|
|
||||||
|
|
||||||
int number = int.Parse(lastDigits.Groups[0].Value);
|
|
||||||
|
|
||||||
number++;
|
|
||||||
|
|
||||||
return lastDigitsRegex.Replace(tag, number.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void UpdateEdgegapAppTag(string tag)
|
|
||||||
{
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
// -batchmode -nographics remains for Unity 2019/2020 support pre-dedicated server builds
|
|
||||||
static string dockerFileText = @"FROM ubuntu:bionic
|
|
||||||
|
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
|
||||||
|
|
||||||
COPY Builds/EdgegapServer /root/build/
|
|
||||||
|
|
||||||
WORKDIR /root/
|
|
||||||
|
|
||||||
RUN chmod +x /root/build/ServerBuild
|
|
||||||
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y ca-certificates && \
|
|
||||||
apt-get clean && \
|
|
||||||
update-ca-certificates
|
|
||||||
|
|
||||||
ENTRYPOINT [ ""/root/build/ServerBuild"", ""-batchmode"", ""-nographics""]
|
|
||||||
";
|
|
||||||
|
|
||||||
/// <summary>Run a Docker cmd with streaming log response. TODO: Plugin to other Docker cmds</summary>
|
|
||||||
/// <returns>Throws if logs contain "ERROR"</returns>
|
|
||||||
///
|
|
||||||
/// <param name="registryUrl">ex: "registry.edgegap.com"</param>
|
|
||||||
/// <param name="repoUsername">ex: "robot$mycompany-asdf+client-push"</param>
|
|
||||||
/// <param name="repoPasswordToken">Different from ApiToken; sometimes called "Container Registry Password"</param>
|
|
||||||
/// <param name="onStatusUpdate">Log stream</param>
|
|
||||||
// MIRROR CHANGE: CROSS PLATFORM SUPPORT
|
|
||||||
static async Task<bool> RunCommand_DockerLogin(
|
|
||||||
string registryUrl,
|
|
||||||
string repoUsername,
|
|
||||||
string repoPasswordToken,
|
|
||||||
Action<string> outputReciever = null, Action<string> errorReciever = null)
|
|
||||||
{
|
|
||||||
// TODO: Use --password-stdin for security (!) This is no easy task for child Process | https://stackoverflow.com/q/51489359/6541639
|
|
||||||
// (!) Don't use single quotes for cross-platform support (works unexpectedly in `cmd`).
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
#if UNITY_EDITOR_WIN
|
|
||||||
await RunCommand("cmd.exe", $"/c docker login -u \"{repoUsername}\" --password \"{repoPasswordToken}\" \"{registryUrl}\"", outputReciever, errorReciever);
|
|
||||||
#elif UNITY_EDITOR_OSX
|
|
||||||
await RunCommand("/bin/bash", $"-c \"docker login -u \"{repoUsername}\" --password \"{repoPasswordToken}\" \"{registryUrl}\"\"", outputReciever, errorReciever);
|
|
||||||
#elif UNITY_EDITOR_LINUX
|
|
||||||
await RunCommand("/bin/bash", $"-c \"docker login -u \"{repoUsername}\" --password \"{repoPasswordToken}\" \"{registryUrl}\"\"", outputReciever, errorReciever);
|
|
||||||
#else
|
|
||||||
Debug.LogError("The platform is not supported yet.");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.LogError($"Error: {e}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// v2: Login to Docker Registry via RunCommand(), returning streamed log messages:
|
|
||||||
/// "docker login {registryUrl} {repository} {repoUsername} {repoPasswordToken}"
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="registryUrl">ex: "registry.edgegap.com"</param>
|
|
||||||
/// <param name="repoUsername">ex: "robot$mycompany-asdf+client-push"</param>
|
|
||||||
/// <param name="repoPasswordToken">Different from ApiToken; sometimes called "Container Registry Password"</param>
|
|
||||||
/// <param name="onStatusUpdate">Log stream</param>
|
|
||||||
/// <returns>isSuccess</returns>
|
|
||||||
public static async Task<bool> LoginContainerRegistry(
|
|
||||||
string registryUrl,
|
|
||||||
string repoUsername,
|
|
||||||
string repoPasswordToken,
|
|
||||||
Action<string> onStatusUpdate)
|
|
||||||
{
|
|
||||||
string error = null;
|
|
||||||
await RunCommand_DockerLogin(registryUrl, repoUsername, repoPasswordToken, onStatusUpdate, msg => error = msg); // MIRROR CHANGE
|
|
||||||
if (error.Contains("ERROR"))
|
|
||||||
{
|
|
||||||
Debug.LogError(error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 97dadab2a073d8b47bf9a270401f0a8f
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,27 +0,0 @@
|
|||||||
#if UNITY_EDITOR
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine.UIElements;
|
|
||||||
using Edgegap;
|
|
||||||
|
|
||||||
[CustomEditor(typeof(EdgegapToolScript))]
|
|
||||||
public class EdgegapPluginScriptEditor : Editor
|
|
||||||
{
|
|
||||||
VisualElement _serverDataContainer;
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
_serverDataContainer = EdgegapServerDataManager.GetServerDataVisualTree();
|
|
||||||
EdgegapServerDataManager.RegisterServerDataContainer(_serverDataContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDisable()
|
|
||||||
{
|
|
||||||
EdgegapServerDataManager.DeregisterServerDataContainer(_serverDataContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override VisualElement CreateInspectorGUI()
|
|
||||||
{
|
|
||||||
return _serverDataContainer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: c4c676ae6dcca0e458c6a8f06571f8fc
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,81 +0,0 @@
|
|||||||
.row__port-table {
|
|
||||||
padding: 2px 4px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
width: auto;
|
|
||||||
justify-content: space-around;
|
|
||||||
-unity-text-align: middle-left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row__port-table > * {
|
|
||||||
width: 0px;
|
|
||||||
flex-grow: 1;
|
|
||||||
align-self: center;
|
|
||||||
margin: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.focusable:hover {
|
|
||||||
background-color: rgba(0,0,0,0.2);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row__dns {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
width: auto;
|
|
||||||
justify-content: space-between;
|
|
||||||
-unity-text-align: middle-left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row__status {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
width: auto;
|
|
||||||
justify-content: space-between;
|
|
||||||
-unity-text-align: middle-left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label__header {
|
|
||||||
-unity-font-style: bold
|
|
||||||
}
|
|
||||||
|
|
||||||
.label__status {
|
|
||||||
-unity-font-style: bold;
|
|
||||||
border-radius: 2px;
|
|
||||||
width: 100px;
|
|
||||||
color: #fff;
|
|
||||||
-unity-text-align: middle-center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label__info-text {
|
|
||||||
padding: 8px;
|
|
||||||
margin: 4px;
|
|
||||||
border-radius: 3px;
|
|
||||||
-unity-text-align: middle-center;
|
|
||||||
white-space: normal;
|
|
||||||
background-color: rgba(42, 42, 42, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
margin: 8px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg--secondary {
|
|
||||||
background-color: #8a8a8a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg--success {
|
|
||||||
background-color: #90be6d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg--danger {
|
|
||||||
background-color: #f94144;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg--warning {
|
|
||||||
background-color: #f9c74f;
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: da5e3f58bd8cde14789f7c61df3f59f4
|
|
||||||
ScriptedImporter:
|
|
||||||
internalIDToNameTable: []
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
disableValidation: 0
|
|
@ -1,242 +0,0 @@
|
|||||||
using IO.Swagger.Model;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UIElements;
|
|
||||||
|
|
||||||
namespace Edgegap
|
|
||||||
{
|
|
||||||
static class EdgegapServerDataManagerUtils
|
|
||||||
{
|
|
||||||
public static Label GetHeader(string text)
|
|
||||||
{
|
|
||||||
Label header = new Label(text);
|
|
||||||
header.AddToClassList("label__header");
|
|
||||||
|
|
||||||
return header;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static VisualElement GetHeaderRow()
|
|
||||||
{
|
|
||||||
VisualElement row = new VisualElement();
|
|
||||||
row.AddToClassList("row__port-table");
|
|
||||||
row.AddToClassList("label__header");
|
|
||||||
|
|
||||||
row.Add(new Label("Name"));
|
|
||||||
row.Add(new Label("External"));
|
|
||||||
row.Add(new Label("Internal"));
|
|
||||||
row.Add(new Label("ProtocolStr"));
|
|
||||||
row.Add(new Label("Link"));
|
|
||||||
|
|
||||||
return row;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static VisualElement GetRowFromPortResponse(PortMapping port)
|
|
||||||
{
|
|
||||||
VisualElement row = new VisualElement();
|
|
||||||
row.AddToClassList("row__port-table");
|
|
||||||
row.AddToClassList("focusable");
|
|
||||||
|
|
||||||
|
|
||||||
row.Add(new Label(port.Name));
|
|
||||||
row.Add(new Label(port.External.ToString()));
|
|
||||||
row.Add(new Label(port.Internal.ToString()));
|
|
||||||
row.Add(new Label(port.Protocol));
|
|
||||||
row.Add(GetCopyButton("Copy", port.Link));
|
|
||||||
|
|
||||||
return row;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Button GetCopyButton(string btnText, string copiedText)
|
|
||||||
{
|
|
||||||
Button copyBtn = new Button();
|
|
||||||
copyBtn.text = btnText;
|
|
||||||
copyBtn.clickable.clicked += () => GUIUtility.systemCopyBuffer = copiedText;
|
|
||||||
|
|
||||||
return copyBtn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Button GetLinkButton(string btnText, string targetUrl)
|
|
||||||
{
|
|
||||||
Button copyBtn = new Button();
|
|
||||||
copyBtn.text = btnText;
|
|
||||||
copyBtn.clickable.clicked += () => UnityEngine.Application.OpenURL(targetUrl);
|
|
||||||
|
|
||||||
return copyBtn;
|
|
||||||
}
|
|
||||||
public static Label GetInfoText(string innerText)
|
|
||||||
{
|
|
||||||
Label infoText = new Label(innerText);
|
|
||||||
infoText.AddToClassList("label__info-text");
|
|
||||||
|
|
||||||
return infoText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Utility class to centrally manage the Edgegap server data, and create / update the elements displaying the server info.
|
|
||||||
/// </summary>
|
|
||||||
public static class EdgegapServerDataManager
|
|
||||||
{
|
|
||||||
internal static Status _serverData;
|
|
||||||
private static ApiEnvironment _apiEnvironment;
|
|
||||||
|
|
||||||
// UI elements
|
|
||||||
private static readonly StyleSheet _serverDataStylesheet;
|
|
||||||
private static readonly List<VisualElement> _serverDataContainers = new List<VisualElement>();
|
|
||||||
|
|
||||||
public static Status GetServerStatus() => _serverData;
|
|
||||||
|
|
||||||
static EdgegapServerDataManager()
|
|
||||||
{
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
_serverDataStylesheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Edgegap/Editor/EdgegapServerData.uss");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
public static void RegisterServerDataContainer(VisualElement serverDataContainer)
|
|
||||||
{
|
|
||||||
_serverDataContainers.Add(serverDataContainer);
|
|
||||||
}
|
|
||||||
public static void DeregisterServerDataContainer(VisualElement serverDataContainer)
|
|
||||||
{
|
|
||||||
_serverDataContainers.Remove(serverDataContainer);
|
|
||||||
}
|
|
||||||
public static void SetServerData(Status serverData, ApiEnvironment apiEnvironment)
|
|
||||||
{
|
|
||||||
_serverData = serverData;
|
|
||||||
_apiEnvironment = apiEnvironment;
|
|
||||||
RefreshServerDataContainers();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static VisualElement GetStatusSection()
|
|
||||||
{
|
|
||||||
ServerStatus serverStatus = _serverData.GetServerStatus();
|
|
||||||
string dashboardUrl = _apiEnvironment.GetDashboardUrl();
|
|
||||||
string requestId = _serverData.RequestId;
|
|
||||||
string deploymentDashboardUrl = "";
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(requestId) && !string.IsNullOrEmpty(dashboardUrl))
|
|
||||||
{
|
|
||||||
deploymentDashboardUrl = $"{dashboardUrl}/arbitrium/deployment/read/{requestId}/";
|
|
||||||
}
|
|
||||||
|
|
||||||
VisualElement container = new VisualElement();
|
|
||||||
container.AddToClassList("container");
|
|
||||||
|
|
||||||
container.Add(EdgegapServerDataManagerUtils.GetHeader("Server Status"));
|
|
||||||
|
|
||||||
VisualElement row = new VisualElement();
|
|
||||||
row.AddToClassList("row__status");
|
|
||||||
|
|
||||||
// Status pill
|
|
||||||
Label statusLabel = new Label(serverStatus.GetLabelText());
|
|
||||||
statusLabel.AddToClassList(serverStatus.GetStatusBgClass());
|
|
||||||
statusLabel.AddToClassList("label__status");
|
|
||||||
row.Add(statusLabel);
|
|
||||||
|
|
||||||
// Link to dashboard
|
|
||||||
if (!string.IsNullOrEmpty(deploymentDashboardUrl))
|
|
||||||
{
|
|
||||||
row.Add(EdgegapServerDataManagerUtils.GetLinkButton("See in the dashboard", deploymentDashboardUrl));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
row.Add(new Label("Could not resolve link to this deployment"));
|
|
||||||
}
|
|
||||||
|
|
||||||
container.Add(row);
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static VisualElement GetDnsSection()
|
|
||||||
{
|
|
||||||
string serverDns = _serverData.Fqdn;
|
|
||||||
|
|
||||||
VisualElement container = new VisualElement();
|
|
||||||
container.AddToClassList("container");
|
|
||||||
|
|
||||||
container.Add(EdgegapServerDataManagerUtils.GetHeader("Server DNS"));
|
|
||||||
|
|
||||||
VisualElement row = new VisualElement();
|
|
||||||
row.AddToClassList("row__dns");
|
|
||||||
row.AddToClassList("focusable");
|
|
||||||
|
|
||||||
row.Add(new Label(serverDns));
|
|
||||||
row.Add(EdgegapServerDataManagerUtils.GetCopyButton("Copy", serverDns));
|
|
||||||
|
|
||||||
container.Add(row);
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static VisualElement GetPortsSection()
|
|
||||||
{
|
|
||||||
List<PortMapping> serverPorts = _serverData.Ports.Values.ToList();
|
|
||||||
|
|
||||||
VisualElement container = new VisualElement();
|
|
||||||
container.AddToClassList("container");
|
|
||||||
|
|
||||||
container.Add(EdgegapServerDataManagerUtils.GetHeader("Server PortsDict"));
|
|
||||||
container.Add(EdgegapServerDataManagerUtils.GetHeaderRow());
|
|
||||||
|
|
||||||
VisualElement portList = new VisualElement();
|
|
||||||
|
|
||||||
if (serverPorts.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (PortMapping port in serverPorts)
|
|
||||||
{
|
|
||||||
portList.Add(EdgegapServerDataManagerUtils.GetRowFromPortResponse(port));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
portList.Add(new Label("No port configured for this app version."));
|
|
||||||
}
|
|
||||||
|
|
||||||
container.Add(portList);
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static VisualElement GetServerDataVisualTree()
|
|
||||||
{
|
|
||||||
VisualElement serverDataTree = new VisualElement();
|
|
||||||
serverDataTree.styleSheets.Add(_serverDataStylesheet);
|
|
||||||
|
|
||||||
bool hasServerData = _serverData != null;
|
|
||||||
bool isReady = hasServerData && _serverData.GetServerStatus().IsOneOf(ServerStatus.Ready, ServerStatus.Error);
|
|
||||||
|
|
||||||
if (hasServerData)
|
|
||||||
{
|
|
||||||
serverDataTree.Add(GetStatusSection());
|
|
||||||
|
|
||||||
if (isReady)
|
|
||||||
{
|
|
||||||
serverDataTree.Add(GetDnsSection());
|
|
||||||
serverDataTree.Add(GetPortsSection());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
serverDataTree.Add(EdgegapServerDataManagerUtils.GetInfoText("Additional information will be displayed when the server is ready."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
serverDataTree.Add(EdgegapServerDataManagerUtils.GetInfoText("Server data will be displayed here when a server is running."));
|
|
||||||
}
|
|
||||||
|
|
||||||
return serverDataTree;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void RefreshServerDataContainers()
|
|
||||||
{
|
|
||||||
foreach (VisualElement serverDataContainer in _serverDataContainers)
|
|
||||||
{
|
|
||||||
serverDataContainer.Clear();
|
|
||||||
serverDataContainer.Add(GetServerDataVisualTree()); // Cannot reuse a same instance of VisualElement
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 39f5f27c13279a34eb116630a00e41c2
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,12 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
using Edgegap;
|
|
||||||
using IO.Swagger.Model;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This script acts as an interface to display and use the necessary variables from the Edgegap tool.
|
|
||||||
/// The server info can be accessed from the tool window, as well as through the public script property.
|
|
||||||
/// </summary>
|
|
||||||
public class EdgegapToolScript : MonoBehaviour
|
|
||||||
{
|
|
||||||
public Status ServerStatus => EdgegapServerDataManager.GetServerStatus();
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5963202433da25448a22def99f5a598b
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,988 +0,0 @@
|
|||||||
// MIRROR CHANGE: disable this completely. otherwise InitUIElements can still throw NRE.
|
|
||||||
/*
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UIElements;
|
|
||||||
using UnityEditor.UIElements;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using IO.Swagger.Model;
|
|
||||||
using UnityEditor.Build.Reporting;
|
|
||||||
using Application = UnityEngine.Application;
|
|
||||||
|
|
||||||
namespace Edgegap
|
|
||||||
{
|
|
||||||
public class EdgegapWindow : EditorWindow
|
|
||||||
{
|
|
||||||
// MIRROR CHANGE: create HTTPClient in-place to avoid InvalidOperationExceptions when reusing
|
|
||||||
// static readonly HttpClient _httpClient = new HttpClient();
|
|
||||||
// END MIRROR CHANGE
|
|
||||||
|
|
||||||
const string EditorDataSerializationName = "EdgegapSerializationData";
|
|
||||||
const int ServerStatusCronjobIntervalMs = 10000; // Interval at which the server status is updated
|
|
||||||
|
|
||||||
// MIRROR CHANGE
|
|
||||||
// get the path of this .cs file so we don't need to hardcode paths to
|
|
||||||
// the .uxml and .uss files:
|
|
||||||
// https://forum.unity.com/threads/too-many-hard-coded-paths-in-the-templates-and-documentation.728138/
|
|
||||||
// this way users can move this folder without breaking UIToolkit paths.
|
|
||||||
internal string StylesheetPath =>
|
|
||||||
Path.GetDirectoryName(AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(this)));
|
|
||||||
// END MIRROR CHANGE
|
|
||||||
|
|
||||||
readonly System.Timers.Timer _updateServerStatusCronjob = new System.Timers.Timer(ServerStatusCronjobIntervalMs);
|
|
||||||
|
|
||||||
[SerializeField] string _userExternalIp;
|
|
||||||
[SerializeField] string _apiKey;
|
|
||||||
[SerializeField] ApiEnvironment _apiEnvironment;
|
|
||||||
[SerializeField] string _appName;
|
|
||||||
[SerializeField] string _appVersionName;
|
|
||||||
[SerializeField] string _deploymentRequestId;
|
|
||||||
|
|
||||||
[SerializeField] string _containerRegistry;
|
|
||||||
[SerializeField] string _containerImageRepo;
|
|
||||||
[SerializeField] string _containerImageTag;
|
|
||||||
[SerializeField] bool _autoIncrementTag = true;
|
|
||||||
|
|
||||||
|
|
||||||
VisualTreeAsset _visualTree;
|
|
||||||
bool _shouldUpdateServerStatus = false;
|
|
||||||
|
|
||||||
// Interactable elements
|
|
||||||
EnumField _apiEnvironmentSelect;
|
|
||||||
TextField _apiKeyInput;
|
|
||||||
TextField _appNameInput;
|
|
||||||
TextField _appVersionNameInput;
|
|
||||||
TextField _containerRegistryInput;
|
|
||||||
TextField _containerImageRepoInput;
|
|
||||||
TextField _containerImageTagInput;
|
|
||||||
Toggle _autoIncrementTagInput;
|
|
||||||
Button _connectionButton;
|
|
||||||
Button _serverActionButton;
|
|
||||||
Button _documentationBtn;
|
|
||||||
Button _buildAndPushServerBtn;
|
|
||||||
|
|
||||||
// Readonly elements
|
|
||||||
Label _connectionStatusLabel;
|
|
||||||
VisualElement _serverDataContainer;
|
|
||||||
|
|
||||||
// server data manager
|
|
||||||
StyleSheet _serverDataStylesheet;
|
|
||||||
List<VisualElement> _serverDataContainers = new List<VisualElement>();
|
|
||||||
|
|
||||||
[Obsolete("See EdgegapWindowV2.ShowEdgegapToolWindow()")]
|
|
||||||
// [MenuItem("Edgegap/Server Management")]
|
|
||||||
public static void ShowEdgegapToolWindow()
|
|
||||||
{
|
|
||||||
EdgegapWindow window = GetWindow<EdgegapWindow>();
|
|
||||||
window.titleContent = new GUIContent("Edgegap Hosting"); // MIRROR CHANGE
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void OnEnable()
|
|
||||||
{
|
|
||||||
// Set root VisualElement and style
|
|
||||||
// BEGIN MIRROR CHANGE
|
|
||||||
_visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>($"{StylesheetPath}/EdgegapWindow.uxml");
|
|
||||||
StyleSheet styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>($"{StylesheetPath}/EdgegapWindow.uss");
|
|
||||||
_serverDataStylesheet = AssetDatabase.LoadAssetAtPath<StyleSheet>($"{StylesheetPath}/EdgegapServerData.uss");
|
|
||||||
// END MIRROR CHANGE
|
|
||||||
rootVisualElement.styleSheets.Add(styleSheet);
|
|
||||||
|
|
||||||
LoadToolData();
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(_userExternalIp))
|
|
||||||
{
|
|
||||||
_userExternalIp = GetExternalIpAddress();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Update()
|
|
||||||
{
|
|
||||||
if (_shouldUpdateServerStatus)
|
|
||||||
{
|
|
||||||
_shouldUpdateServerStatus = false;
|
|
||||||
UpdateServerStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CreateGUI()
|
|
||||||
{
|
|
||||||
rootVisualElement.Clear();
|
|
||||||
_visualTree.CloneTree(rootVisualElement);
|
|
||||||
|
|
||||||
InitUIElements();
|
|
||||||
SyncFormWithObject();
|
|
||||||
|
|
||||||
bool hasActiveDeployment = !string.IsNullOrEmpty(_deploymentRequestId);
|
|
||||||
|
|
||||||
if (hasActiveDeployment)
|
|
||||||
{
|
|
||||||
RestoreActiveDeployment();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DisconnectCallback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void OnDestroy()
|
|
||||||
{
|
|
||||||
bool deploymentActive = !string.IsNullOrEmpty(_deploymentRequestId);
|
|
||||||
|
|
||||||
if (deploymentActive)
|
|
||||||
{
|
|
||||||
EditorUtility.DisplayDialog(
|
|
||||||
"Warning",
|
|
||||||
$"You have an active deployment ({_deploymentRequestId}) that won't be stopped automatically.",
|
|
||||||
"Ok"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void OnDisable()
|
|
||||||
{
|
|
||||||
SyncObjectWithForm();
|
|
||||||
SaveToolData();
|
|
||||||
DeregisterServerDataContainer(_serverDataContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds the form inputs to the associated variables and initializes the inputs as required.
|
|
||||||
/// Requires the VisualElements to be loaded before this call. Otherwise, the elements cannot be found.
|
|
||||||
/// </summary>
|
|
||||||
void InitUIElements()
|
|
||||||
{
|
|
||||||
_apiEnvironmentSelect = rootVisualElement.Q<EnumField>("environmentSelect");
|
|
||||||
_apiKeyInput = rootVisualElement.Q<TextField>("apiKey");
|
|
||||||
_appNameInput = rootVisualElement.Q<TextField>("appName");
|
|
||||||
_appVersionNameInput = rootVisualElement.Q<TextField>("appVersionName");
|
|
||||||
|
|
||||||
_containerRegistryInput = rootVisualElement.Q<TextField>("containerRegistry");
|
|
||||||
_containerImageRepoInput = rootVisualElement.Q<TextField>("containerImageRepo");
|
|
||||||
_containerImageTagInput = rootVisualElement.Q<TextField>("tag");
|
|
||||||
_autoIncrementTagInput = rootVisualElement.Q<Toggle>("autoIncrementTag");
|
|
||||||
|
|
||||||
_connectionButton = rootVisualElement.Q<Button>("connectionBtn");
|
|
||||||
_serverActionButton = rootVisualElement.Q<Button>("serverActionBtn");
|
|
||||||
_documentationBtn = rootVisualElement.Q<Button>("documentationBtn");
|
|
||||||
_buildAndPushServerBtn = rootVisualElement.Q<Button>("buildAndPushBtn");
|
|
||||||
_buildAndPushServerBtn.clickable.clicked += BuildAndPushServer;
|
|
||||||
|
|
||||||
_connectionStatusLabel = rootVisualElement.Q<Label>("connectionStatusLabel");
|
|
||||||
_serverDataContainer = rootVisualElement.Q<VisualElement>("serverDataContainer");
|
|
||||||
|
|
||||||
// Load initial server data UI element and register for updates.
|
|
||||||
VisualElement serverDataElement = GetServerDataVisualTree();
|
|
||||||
RegisterServerDataContainer(serverDataElement);
|
|
||||||
_serverDataContainer.Clear();
|
|
||||||
_serverDataContainer.Add(serverDataElement);
|
|
||||||
|
|
||||||
_documentationBtn.clickable.clicked += OpenDocumentationCallback;
|
|
||||||
|
|
||||||
// Init the ApiEnvironment dropdown
|
|
||||||
_apiEnvironmentSelect.Init(ApiEnvironment.Console);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// With a call to an external resource, determines the current user's public IP address.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>External IP address</returns>
|
|
||||||
string GetExternalIpAddress()
|
|
||||||
{
|
|
||||||
string externalIpString = new WebClient()
|
|
||||||
.DownloadString("http://icanhazip.com")
|
|
||||||
.Replace("\\r\\n", "")
|
|
||||||
.Replace("\\n", "")
|
|
||||||
.Trim();
|
|
||||||
IPAddress externalIp = IPAddress.Parse(externalIpString);
|
|
||||||
|
|
||||||
return externalIp.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenDocumentationCallback()
|
|
||||||
{
|
|
||||||
// MIRROR CHANGE
|
|
||||||
// ApiEnvironment selectedApiEnvironment = (ApiEnvironment)_apiEnvironmentSelect.value;
|
|
||||||
// string documentationUrl = selectedApiEnvironment.GetDocumentationUrl();
|
|
||||||
//
|
|
||||||
// if (!string.IsNullOrEmpty(documentationUrl))
|
|
||||||
// {
|
|
||||||
// UnityEngine.Application.OpenURL(documentationUrl);
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// string apiEnvName = Enum.GetName(typeof(ApiEnvironment), selectedApiEnvironment);
|
|
||||||
// Debug.LogWarning($"Could not open documentation for api environment {apiEnvName}: No documentation URL.");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// link to the easiest documentation
|
|
||||||
Application.OpenURL("https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide");
|
|
||||||
// END MIRROR CHANGE
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConnectCallback()
|
|
||||||
{
|
|
||||||
ApiEnvironment selectedApiEnvironment = (ApiEnvironment)_apiEnvironmentSelect.value;
|
|
||||||
string selectedAppName = _appNameInput.value;
|
|
||||||
string selectedVersionName = _appVersionNameInput.value;
|
|
||||||
string selectedApiKey = _apiKeyInput.value;
|
|
||||||
|
|
||||||
bool validAppName = !string.IsNullOrEmpty(selectedAppName) && !string.IsNullOrWhiteSpace(selectedAppName);
|
|
||||||
bool validVersionName = !string.IsNullOrEmpty(selectedVersionName) && !string.IsNullOrWhiteSpace(selectedVersionName);
|
|
||||||
bool validApiKey = selectedApiKey.StartsWith("token ");
|
|
||||||
|
|
||||||
if (validAppName && validVersionName && validApiKey)
|
|
||||||
{
|
|
||||||
string apiKeyValue = selectedApiKey.Substring(6);
|
|
||||||
Connect(selectedApiEnvironment, selectedAppName, selectedVersionName, apiKeyValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EditorUtility.DisplayDialog(
|
|
||||||
"Could not connect - Invalid data",
|
|
||||||
"The data provided is invalid. " +
|
|
||||||
"Make sure every field is filled, and that you provide your complete Edgegap API token " +
|
|
||||||
"(including the \"token\" part).",
|
|
||||||
"Ok"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MIRROR CHANGE: create HTTPClient in-place to avoid InvalidOperationExceptions when reusing
|
|
||||||
HttpClient CreateHttpClient()
|
|
||||||
{
|
|
||||||
HttpClient httpClient = new HttpClient();
|
|
||||||
httpClient.BaseAddress = new Uri(_apiEnvironment.GetApiUrl());
|
|
||||||
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
|
||||||
string token = _apiKeyInput.value.Substring(6);
|
|
||||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("token", token);
|
|
||||||
return httpClient;
|
|
||||||
}
|
|
||||||
// END MIRROR CHANGE
|
|
||||||
|
|
||||||
async void Connect(
|
|
||||||
ApiEnvironment selectedApiEnvironment,
|
|
||||||
string selectedAppName,
|
|
||||||
string selectedAppVersionName,
|
|
||||||
string selectedApiTokenValue
|
|
||||||
)
|
|
||||||
{
|
|
||||||
SetToolUIState(ToolState.Connecting);
|
|
||||||
|
|
||||||
// Make HTTP request
|
|
||||||
HttpClient _httpClient = CreateHttpClient(); // MIRROR CHANGE: create HTTPClient in-place to avoid InvalidOperationExceptions when reusing
|
|
||||||
string path = $"/v1/app/{selectedAppName}/version/{selectedAppVersionName}"; // MIRROR CHANGE: use selectedAppName and selectedAppVersionName instead of _appName & _appVersionName
|
|
||||||
HttpResponseMessage response = await _httpClient.GetAsync(path);
|
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
SyncObjectWithForm();
|
|
||||||
SetToolUIState(ToolState.Connected);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int status = (int)response.StatusCode;
|
|
||||||
string title;
|
|
||||||
string message;
|
|
||||||
|
|
||||||
if (status == 401)
|
|
||||||
{
|
|
||||||
string apiEnvName = Enum.GetName(typeof(ApiEnvironment), selectedApiEnvironment);
|
|
||||||
title = "Invalid credentials";
|
|
||||||
message = $"Could not find an Edgegap account with this API key for the {apiEnvName} environment.";
|
|
||||||
}
|
|
||||||
else if (status == 404)
|
|
||||||
{
|
|
||||||
title = "App not found";
|
|
||||||
message = $"Could not find app {selectedAppName} with version {selectedAppVersionName}.";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
title = "Oops";
|
|
||||||
message = $"There was an error while connecting you to the Edgegap API. Please try again later.";
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorUtility.DisplayDialog(title, message, "Ok");
|
|
||||||
SetToolUIState(ToolState.Disconnected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisconnectCallback()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(_deploymentRequestId))
|
|
||||||
{
|
|
||||||
SetToolUIState(ToolState.Disconnected);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EditorUtility.DisplayDialog("Cannot disconnect", "Make sure no server is running in the Edgegap tool before disconnecting", "Ok");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float ProgressCounter = 0;
|
|
||||||
|
|
||||||
// MIRROR CHANGE: added title parameter for more detailed progress while waiting
|
|
||||||
void ShowBuildWorkInProgress(string title, string status)
|
|
||||||
{
|
|
||||||
EditorUtility.DisplayProgressBar(title, status, ProgressCounter++ / 50);
|
|
||||||
}
|
|
||||||
// END MIRROR CHANGE
|
|
||||||
|
|
||||||
async void BuildAndPushServer()
|
|
||||||
{
|
|
||||||
SetToolUIState(ToolState.Building);
|
|
||||||
|
|
||||||
SyncObjectWithForm();
|
|
||||||
ProgressCounter = 0;
|
|
||||||
Action<string> onError = (msg) =>
|
|
||||||
{
|
|
||||||
EditorUtility.DisplayDialog("Error", msg, "Ok");
|
|
||||||
SetToolUIState(ToolState.Connected);
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// check for installation and setup docker file
|
|
||||||
if (!await EdgegapBuildUtils.DockerSetupAndInstallationCheck())
|
|
||||||
{
|
|
||||||
onError("Docker installation not found. Docker can be downloaded from:\n\nhttps://www.docker.com/");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// MIRROR CHANGE
|
|
||||||
// make sure Linux build target is installed before attemping to build.
|
|
||||||
// if it's not installed, tell the user about it.
|
|
||||||
if (!BuildPipeline.IsBuildTargetSupported(BuildTargetGroup.Standalone, BuildTarget.StandaloneLinux64))
|
|
||||||
{
|
|
||||||
onError($"Linux Build Support is missing.\n\nPlease open Unity Hub -> Installs -> Unity {Application.unityVersion} -> Add Modules -> Linux Build Support (IL2CPP & Mono & Dedicated Server) -> Install\n\nAfterwards restart Unity!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// END MIRROR CHANGE
|
|
||||||
|
|
||||||
// create server build
|
|
||||||
BuildReport buildResult = EdgegapBuildUtils.BuildServer();
|
|
||||||
if (buildResult.summary.result != BuildResult.Succeeded)
|
|
||||||
{
|
|
||||||
onError("Edgegap build failed, please check the Unity console logs.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string registry = _containerRegistry;
|
|
||||||
string imageName = _containerImageRepo;
|
|
||||||
string tag = _containerImageTag;
|
|
||||||
|
|
||||||
// MIRROR CHANGE ///////////////////////////////////////////////
|
|
||||||
// registry, repository and tag can not contain whitespaces.
|
|
||||||
// otherwise the docker command will throw an error:
|
|
||||||
// "ERROR: "docker buildx build" requires exactly 1 argument."
|
|
||||||
// catch this early and notify the user immediately.
|
|
||||||
if (registry.Contains(" "))
|
|
||||||
{
|
|
||||||
onError($"Container Registry is not allowed to contain whitespace: '{registry}'");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imageName.Contains(" "))
|
|
||||||
{
|
|
||||||
onError($"Image Repository is not allowed to contain whitespace: '{imageName}'");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tag.Contains(" "))
|
|
||||||
{
|
|
||||||
onError($"Tag is not allowed to contain whitespace: '{tag}'");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// END MIRROR CHANGE ///////////////////////////////////////////
|
|
||||||
|
|
||||||
// increment tag for quicker iteration
|
|
||||||
if (_autoIncrementTag)
|
|
||||||
{
|
|
||||||
tag = EdgegapBuildUtils.IncrementTag(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create docker image
|
|
||||||
await EdgegapBuildUtils.RunCommand_DockerBuild(registry, imageName, tag, status => ShowBuildWorkInProgress("Building Docker Image", status));
|
|
||||||
|
|
||||||
SetToolUIState(ToolState.Pushing);
|
|
||||||
|
|
||||||
// push docker image
|
|
||||||
(bool result, string error) = await EdgegapBuildUtils.RunCommand_DockerPush(registry, imageName, tag, status => ShowBuildWorkInProgress("Uploading Docker Image (this may take a while)", status));
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
// catch common issues with detailed solutions
|
|
||||||
if (error.Contains("Cannot connect to the Docker daemon"))
|
|
||||||
{
|
|
||||||
onError($"{error}\nTo solve this, you can install and run Docker Desktop from:\n\nhttps://www.docker.com/products/docker-desktop");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.Contains("unauthorized to access repository"))
|
|
||||||
{
|
|
||||||
onError($"Docker authorization failed:\n\n{error}\nTo solve this, you can open a terminal and enter 'docker login {registry}', then enter your credentials.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// project not found?
|
|
||||||
if (Regex.IsMatch(error, @".*project .* not found.*", RegexOptions.IgnoreCase))
|
|
||||||
{
|
|
||||||
onError($"{error}\nTo solve this, make sure that Image Repository is 'project/game' where 'project' is from the Container Registry page on the Edgegap website.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise show generic error message
|
|
||||||
onError($"Unable to push docker image to registry. Please make sure you're logged in to {registry} and check the following error:\n\n{error}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update edgegap server settings for new tag
|
|
||||||
ShowBuildWorkInProgress("Build and Push", "Updating server info on Edgegap");
|
|
||||||
await UpdateAppTagOnEdgegap(tag);
|
|
||||||
|
|
||||||
// cleanup
|
|
||||||
_containerImageTag = tag;
|
|
||||||
SyncFormWithObject();
|
|
||||||
SetToolUIState(ToolState.Connected);
|
|
||||||
|
|
||||||
Debug.Log("Server built and pushed successfully");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Debug.LogError(ex);
|
|
||||||
onError($"Edgegap build and push failed with Error: {ex}");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
// MIRROR CHANGE: always clear otherwise it gets stuck there forever!
|
|
||||||
EditorUtility.ClearProgressBar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async Task UpdateAppTagOnEdgegap(string newTag)
|
|
||||||
{
|
|
||||||
string path = $"/v1/app/{_appName}/version/{_appVersionName}";
|
|
||||||
|
|
||||||
// Setup post data
|
|
||||||
AppVersionUpdatePatchData updatePatchData = new AppVersionUpdatePatchData { DockerImage = _containerImageRepo, DockerRegistry = _containerRegistry, DockerTag = newTag };
|
|
||||||
string json = JsonConvert.SerializeObject(updatePatchData);
|
|
||||||
StringContent patchData = new StringContent(json, Encoding.UTF8, "application/json");
|
|
||||||
|
|
||||||
// Make HTTP request
|
|
||||||
HttpClient _httpClient = CreateHttpClient(); // MIRROR CHANGE: create HTTPClient in-place to avoid InvalidOperationExceptions when reusing
|
|
||||||
HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("PATCH"), path);
|
|
||||||
request.Content = patchData;
|
|
||||||
HttpResponseMessage response = await _httpClient.SendAsync(request);
|
|
||||||
string content = await response.Content.ReadAsStringAsync();
|
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
throw new Exception($"Could not update Edgegap server tag. Got {(int)response.StatusCode} with response:\n{content}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async void StartServerCallback()
|
|
||||||
{
|
|
||||||
SetToolUIState(ToolState.ProcessingDeployment); // Prevents being called multiple times.
|
|
||||||
|
|
||||||
const string path = "/v1/deploy";
|
|
||||||
|
|
||||||
// Setup post data
|
|
||||||
DeployPostData deployPostData = new DeployPostData(_appName, _appVersionName, new List<string> { _userExternalIp });
|
|
||||||
string json = JsonConvert.SerializeObject(deployPostData);
|
|
||||||
StringContent postData = new StringContent(json, Encoding.UTF8, "application/json");
|
|
||||||
|
|
||||||
// Make HTTP request
|
|
||||||
HttpClient _httpClient = CreateHttpClient(); // MIRROR CHANGE: create HTTPClient in-place to avoid InvalidOperationExceptions when reusing
|
|
||||||
HttpResponseMessage response = await _httpClient.PostAsync(path, postData);
|
|
||||||
string content = await response.Content.ReadAsStringAsync();
|
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
// Parse response
|
|
||||||
Deployment parsedResponse = JsonConvert.DeserializeObject<Deployment>(content);
|
|
||||||
|
|
||||||
_deploymentRequestId = parsedResponse.RequestId;
|
|
||||||
|
|
||||||
UpdateServerStatus();
|
|
||||||
StartServerStatusCronjob();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.LogError($"Could not start Edgegap server. Got {(int)response.StatusCode} with response:\n{content}");
|
|
||||||
SetToolUIState(ToolState.Connected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async void StopServerCallback()
|
|
||||||
{
|
|
||||||
string path = $"/v1/stop/{_deploymentRequestId}";
|
|
||||||
|
|
||||||
// Make HTTP request
|
|
||||||
HttpClient _httpClient = CreateHttpClient(); // MIRROR CHANGE: create HTTPClient in-place to avoid InvalidOperationExceptions when reusing
|
|
||||||
HttpResponseMessage response = await _httpClient.DeleteAsync(path);
|
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
UpdateServerStatus();
|
|
||||||
SetToolUIState(ToolState.ProcessingDeployment);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Parse response
|
|
||||||
string content = await response.Content.ReadAsStringAsync();
|
|
||||||
|
|
||||||
Debug.LogError($"Could not stop Edgegap server. Got {(int)response.StatusCode} with response:\n{content}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StartServerStatusCronjob()
|
|
||||||
{
|
|
||||||
_updateServerStatusCronjob.Elapsed += (sourceObject, elaspedEvent) => _shouldUpdateServerStatus = true;
|
|
||||||
_updateServerStatusCronjob.AutoReset = true;
|
|
||||||
_updateServerStatusCronjob.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void StopServerStatusCronjob() => _updateServerStatusCronjob.Stop();
|
|
||||||
|
|
||||||
async void UpdateServerStatus()
|
|
||||||
{
|
|
||||||
Status serverStatusResponse = await FetchServerStatus();
|
|
||||||
|
|
||||||
ToolState toolState;
|
|
||||||
ServerStatus serverStatus = serverStatusResponse.GetServerStatus();
|
|
||||||
|
|
||||||
if (serverStatus == ServerStatus.Terminated)
|
|
||||||
{
|
|
||||||
SetServerData(null, _apiEnvironment);
|
|
||||||
|
|
||||||
if (_updateServerStatusCronjob.Enabled)
|
|
||||||
{
|
|
||||||
StopServerStatusCronjob();
|
|
||||||
}
|
|
||||||
|
|
||||||
_deploymentRequestId = null;
|
|
||||||
toolState = ToolState.Connected;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetServerData(serverStatusResponse, _apiEnvironment);
|
|
||||||
|
|
||||||
if (serverStatus == ServerStatus.Ready || serverStatus == ServerStatus.Error)
|
|
||||||
{
|
|
||||||
toolState = ToolState.DeploymentRunning;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
toolState = ToolState.ProcessingDeployment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SetToolUIState(toolState);
|
|
||||||
}
|
|
||||||
|
|
||||||
async Task<Status> FetchServerStatus()
|
|
||||||
{
|
|
||||||
string path = $"/v1/status/{_deploymentRequestId}";
|
|
||||||
|
|
||||||
// Make HTTP request
|
|
||||||
HttpClient _httpClient = CreateHttpClient(); // MIRROR CHANGE: create HTTPClient in-place to avoid InvalidOperationExceptions when reusing
|
|
||||||
HttpResponseMessage response = await _httpClient.GetAsync(path);
|
|
||||||
|
|
||||||
// Parse response
|
|
||||||
string content = await response.Content.ReadAsStringAsync();
|
|
||||||
|
|
||||||
Status parsedData;
|
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
parsedData = JsonConvert.DeserializeObject<Status>(content);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((int)response.StatusCode == 400)
|
|
||||||
{
|
|
||||||
Debug.LogError("The deployment that was active in the tool is now unreachable. Considering it Terminated.");
|
|
||||||
parsedData = new Status() { CurrentStatus = ServerStatus.Terminated.GetLabelText() };
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.LogError(
|
|
||||||
$"Could not fetch status of Edgegap deployment {_deploymentRequestId}. " +
|
|
||||||
$"Got {(int)response.StatusCode} with response:\n{content}"
|
|
||||||
);
|
|
||||||
parsedData = new Status() { CurrentStatus = ServerStatus.NA.GetLabelText() };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return parsedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RestoreActiveDeployment()
|
|
||||||
{
|
|
||||||
ConnectCallback();
|
|
||||||
|
|
||||||
_shouldUpdateServerStatus = true;
|
|
||||||
StartServerStatusCronjob();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyncObjectWithForm()
|
|
||||||
{
|
|
||||||
if (_apiKeyInput == null) return; // MIRROR CHANGE: fix NRE when this is called before UI elements were assgned
|
|
||||||
|
|
||||||
_apiKey = _apiKeyInput.value;
|
|
||||||
_apiEnvironment = (ApiEnvironment)_apiEnvironmentSelect.value;
|
|
||||||
_appName = _appNameInput.value;
|
|
||||||
_appVersionName = _appVersionNameInput.value;
|
|
||||||
|
|
||||||
// MIRROR CHANGE ///////////////////////////////////////////////////
|
|
||||||
// registry, repository and tag can not contain whitespaces.
|
|
||||||
// otherwise it'll throw an error:
|
|
||||||
// "ERROR: "docker buildx build" requires exactly 1 argument."
|
|
||||||
// trim whitespace in case users accidentally added some.
|
|
||||||
_containerRegistry = _containerRegistryInput.value.Trim();
|
|
||||||
_containerImageTag = _containerImageTagInput.value.Trim();
|
|
||||||
_containerImageRepo = _containerImageRepoInput.value.Trim();
|
|
||||||
// END MIRROR CHANGE ///////////////////////////////////////////////
|
|
||||||
|
|
||||||
_autoIncrementTag = _autoIncrementTagInput.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyncFormWithObject()
|
|
||||||
{
|
|
||||||
_apiKeyInput.value = _apiKey;
|
|
||||||
_apiEnvironmentSelect.value = _apiEnvironment;
|
|
||||||
_appNameInput.value = _appName;
|
|
||||||
_appVersionNameInput.value = _appVersionName;
|
|
||||||
|
|
||||||
_containerRegistryInput.value = _containerRegistry;
|
|
||||||
_containerImageTagInput.value = _containerImageTag;
|
|
||||||
_containerImageRepoInput.value = _containerImageRepo;
|
|
||||||
_autoIncrementTagInput.value = _autoIncrementTag;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetToolUIState(ToolState toolState)
|
|
||||||
{
|
|
||||||
SetConnectionInfoUI(toolState);
|
|
||||||
SetConnectionButtonUI(toolState);
|
|
||||||
SetServerActionUI(toolState);
|
|
||||||
SetDockerRepoInfoUI(toolState);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetDockerRepoInfoUI(ToolState toolState)
|
|
||||||
{
|
|
||||||
bool connected = toolState.CanStartDeployment();
|
|
||||||
_containerRegistryInput.SetEnabled(connected);
|
|
||||||
_autoIncrementTagInput.SetEnabled(connected);
|
|
||||||
_containerImageRepoInput.SetEnabled(connected);
|
|
||||||
_containerImageTagInput.SetEnabled(connected);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetConnectionInfoUI(ToolState toolState)
|
|
||||||
{
|
|
||||||
bool canEditConnectionInfo = toolState.CanEditConnectionInfo();
|
|
||||||
|
|
||||||
_apiKeyInput.SetEnabled(canEditConnectionInfo);
|
|
||||||
_apiEnvironmentSelect.SetEnabled(canEditConnectionInfo);
|
|
||||||
_appNameInput.SetEnabled(canEditConnectionInfo);
|
|
||||||
_appVersionNameInput.SetEnabled(canEditConnectionInfo);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetConnectionButtonUI(ToolState toolState)
|
|
||||||
{
|
|
||||||
bool canConnect = toolState.CanConnect();
|
|
||||||
bool canDisconnect = toolState.CanDisconnect();
|
|
||||||
|
|
||||||
_connectionButton.SetEnabled(canConnect || canDisconnect);
|
|
||||||
|
|
||||||
// A bit dirty, but ensures the callback is not bound multiple times on the button.
|
|
||||||
_connectionButton.clickable.clicked -= ConnectCallback;
|
|
||||||
_connectionButton.clickable.clicked -= DisconnectCallback;
|
|
||||||
|
|
||||||
if (canConnect || toolState == ToolState.Connecting)
|
|
||||||
{
|
|
||||||
_connectionButton.text = "Connect";
|
|
||||||
_connectionStatusLabel.text = "Awaiting connection";
|
|
||||||
_connectionStatusLabel.RemoveFromClassList("text--success");
|
|
||||||
_connectionButton.clickable.clicked += ConnectCallback;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_connectionButton.text = "Disconnect";
|
|
||||||
_connectionStatusLabel.text = "Connected";
|
|
||||||
_connectionStatusLabel.AddToClassList("text--success");
|
|
||||||
_connectionButton.clickable.clicked += DisconnectCallback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetServerActionUI(ToolState toolState)
|
|
||||||
{
|
|
||||||
bool canStartDeployment = toolState.CanStartDeployment();
|
|
||||||
bool canStopDeployment = toolState.CanStopDeployment();
|
|
||||||
|
|
||||||
// A bit dirty, but ensures the callback is not bound multiple times on the button.
|
|
||||||
_serverActionButton.clickable.clicked -= StartServerCallback;
|
|
||||||
_serverActionButton.clickable.clicked -= StopServerCallback;
|
|
||||||
|
|
||||||
_serverActionButton.SetEnabled(canStartDeployment || canStopDeployment);
|
|
||||||
|
|
||||||
_buildAndPushServerBtn.SetEnabled(canStartDeployment);
|
|
||||||
|
|
||||||
if (canStopDeployment)
|
|
||||||
{
|
|
||||||
_serverActionButton.text = "Stop Server";
|
|
||||||
_serverActionButton.clickable.clicked += StopServerCallback;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_serverActionButton.text = "Start Server";
|
|
||||||
_serverActionButton.clickable.clicked += StartServerCallback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// server data manager /////////////////////////////////////////////////
|
|
||||||
public void RegisterServerDataContainer(VisualElement serverDataContainer)
|
|
||||||
{
|
|
||||||
_serverDataContainers.Add(serverDataContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DeregisterServerDataContainer(VisualElement serverDataContainer)
|
|
||||||
{
|
|
||||||
_serverDataContainers.Remove(serverDataContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetServerData(Status serverData, ApiEnvironment apiEnvironment)
|
|
||||||
{
|
|
||||||
EdgegapServerDataManager._serverData = serverData;
|
|
||||||
RefreshServerDataContainers();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Label GetHeader(string text)
|
|
||||||
{
|
|
||||||
Label header = new Label(text);
|
|
||||||
header.AddToClassList("label__header");
|
|
||||||
|
|
||||||
return header;
|
|
||||||
}
|
|
||||||
|
|
||||||
public VisualElement GetHeaderRow()
|
|
||||||
{
|
|
||||||
VisualElement row = new VisualElement();
|
|
||||||
row.AddToClassList("row__port-table");
|
|
||||||
row.AddToClassList("label__header");
|
|
||||||
|
|
||||||
row.Add(new Label("Name"));
|
|
||||||
row.Add(new Label("External"));
|
|
||||||
row.Add(new Label("Internal"));
|
|
||||||
row.Add(new Label("Protocol"));
|
|
||||||
row.Add(new Label("Link"));
|
|
||||||
|
|
||||||
return row;
|
|
||||||
}
|
|
||||||
|
|
||||||
public VisualElement GetRowFromPortResponse(PortMapping port)
|
|
||||||
{
|
|
||||||
VisualElement row = new VisualElement();
|
|
||||||
row.AddToClassList("row__port-table");
|
|
||||||
row.AddToClassList("focusable");
|
|
||||||
|
|
||||||
|
|
||||||
row.Add(new Label(port.Name));
|
|
||||||
row.Add(new Label(port.External.ToString()));
|
|
||||||
row.Add(new Label(port.Internal.ToString()));
|
|
||||||
row.Add(new Label(port.Protocol));
|
|
||||||
row.Add(GetCopyButton("Copy", port.Link));
|
|
||||||
|
|
||||||
return row;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Button GetCopyButton(string btnText, string copiedText)
|
|
||||||
{
|
|
||||||
Button copyBtn = new Button();
|
|
||||||
copyBtn.text = btnText;
|
|
||||||
copyBtn.clickable.clicked += () => GUIUtility.systemCopyBuffer = copiedText;
|
|
||||||
|
|
||||||
return copyBtn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Button GetLinkButton(string btnText, string targetUrl)
|
|
||||||
{
|
|
||||||
Button copyBtn = new Button();
|
|
||||||
copyBtn.text = btnText;
|
|
||||||
copyBtn.clickable.clicked += () => UnityEngine.Application.OpenURL(targetUrl);
|
|
||||||
|
|
||||||
return copyBtn;
|
|
||||||
}
|
|
||||||
public Label GetInfoText(string innerText)
|
|
||||||
{
|
|
||||||
Label infoText = new Label(innerText);
|
|
||||||
infoText.AddToClassList("label__info-text");
|
|
||||||
|
|
||||||
return infoText;
|
|
||||||
}
|
|
||||||
|
|
||||||
VisualElement GetStatusSection()
|
|
||||||
{
|
|
||||||
ServerStatus serverStatus = EdgegapServerDataManager._serverData.GetServerStatus();
|
|
||||||
string dashboardUrl = _apiEnvironment.GetDashboardUrl();
|
|
||||||
string requestId = EdgegapServerDataManager._serverData.RequestId;
|
|
||||||
string deploymentDashboardUrl = "";
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(requestId) && !string.IsNullOrEmpty(dashboardUrl))
|
|
||||||
{
|
|
||||||
deploymentDashboardUrl = $"{dashboardUrl}/arbitrium/deployment/read/{requestId}/";
|
|
||||||
}
|
|
||||||
|
|
||||||
VisualElement container = new VisualElement();
|
|
||||||
container.AddToClassList("container");
|
|
||||||
|
|
||||||
container.Add(GetHeader("Server Status"));
|
|
||||||
|
|
||||||
VisualElement row = new VisualElement();
|
|
||||||
row.AddToClassList("row__status");
|
|
||||||
|
|
||||||
// Status pill
|
|
||||||
Label statusLabel = new Label(serverStatus.GetLabelText());
|
|
||||||
statusLabel.AddToClassList(serverStatus.GetStatusBgClass());
|
|
||||||
statusLabel.AddToClassList("label__status");
|
|
||||||
row.Add(statusLabel);
|
|
||||||
|
|
||||||
// Link to dashboard
|
|
||||||
if (!string.IsNullOrEmpty(deploymentDashboardUrl))
|
|
||||||
{
|
|
||||||
row.Add(GetLinkButton("See in the dashboard", deploymentDashboardUrl));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
row.Add(new Label("Could not resolve link to this deployment"));
|
|
||||||
}
|
|
||||||
|
|
||||||
container.Add(row);
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
VisualElement GetDnsSection()
|
|
||||||
{
|
|
||||||
string serverDns = EdgegapServerDataManager._serverData.Fqdn;
|
|
||||||
|
|
||||||
VisualElement container = new VisualElement();
|
|
||||||
container.AddToClassList("container");
|
|
||||||
|
|
||||||
container.Add(GetHeader("Server DNS"));
|
|
||||||
|
|
||||||
VisualElement row = new VisualElement();
|
|
||||||
row.AddToClassList("row__dns");
|
|
||||||
row.AddToClassList("focusable");
|
|
||||||
|
|
||||||
row.Add(new Label(serverDns));
|
|
||||||
row.Add(GetCopyButton("Copy", serverDns));
|
|
||||||
|
|
||||||
container.Add(row);
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
VisualElement GetPortsSection()
|
|
||||||
{
|
|
||||||
List<PortMapping> serverPorts = EdgegapServerDataManager._serverData.Ports.Values.ToList();
|
|
||||||
|
|
||||||
VisualElement container = new VisualElement();
|
|
||||||
container.AddToClassList("container");
|
|
||||||
|
|
||||||
container.Add(GetHeader("Server Ports"));
|
|
||||||
container.Add(GetHeaderRow());
|
|
||||||
|
|
||||||
VisualElement portList = new VisualElement();
|
|
||||||
|
|
||||||
if (serverPorts.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (PortMapping port in serverPorts)
|
|
||||||
{
|
|
||||||
portList.Add(GetRowFromPortResponse(port));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
portList.Add(new Label("No port configured for this app version."));
|
|
||||||
}
|
|
||||||
|
|
||||||
container.Add(portList);
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
public VisualElement GetServerDataVisualTree()
|
|
||||||
{
|
|
||||||
VisualElement serverDataTree = new VisualElement();
|
|
||||||
serverDataTree.styleSheets.Add(_serverDataStylesheet);
|
|
||||||
|
|
||||||
bool hasServerData = EdgegapServerDataManager._serverData != null;
|
|
||||||
bool isReady = hasServerData && EdgegapServerDataManager. _serverData.GetServerStatus().IsOneOf(ServerStatus.Ready, ServerStatus.Error);
|
|
||||||
|
|
||||||
if (hasServerData)
|
|
||||||
{
|
|
||||||
serverDataTree.Add(GetStatusSection());
|
|
||||||
|
|
||||||
if (isReady)
|
|
||||||
{
|
|
||||||
serverDataTree.Add(GetDnsSection());
|
|
||||||
serverDataTree.Add(GetPortsSection());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
serverDataTree.Add(GetInfoText("Additional information will be displayed when the server is ready."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
serverDataTree.Add(GetInfoText("Server data will be displayed here when a server is running."));
|
|
||||||
}
|
|
||||||
|
|
||||||
return serverDataTree;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RefreshServerDataContainers()
|
|
||||||
{
|
|
||||||
foreach (VisualElement serverDataContainer in _serverDataContainers)
|
|
||||||
{
|
|
||||||
serverDataContainer.Clear();
|
|
||||||
serverDataContainer.Add(GetServerDataVisualTree()); // Cannot reuse a same instance of VisualElement
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// save & load /////////////////////////////////////////////////////////
|
|
||||||
/// <summary>
|
|
||||||
/// Save the tool's serializable data to the EditorPrefs to allow persistence across restarts.
|
|
||||||
/// Any field with [SerializeField] will be saved.
|
|
||||||
/// </summary>
|
|
||||||
void SaveToolData()
|
|
||||||
{
|
|
||||||
string data = JsonUtility.ToJson(this, false);
|
|
||||||
EditorPrefs.SetString(EditorDataSerializationName, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Load the tool's serializable data from the EditorPrefs to the object, restoring the tool's state.
|
|
||||||
/// </summary>
|
|
||||||
void LoadToolData()
|
|
||||||
{
|
|
||||||
string data = EditorPrefs.GetString(EditorDataSerializationName, JsonUtility.ToJson(this, false));
|
|
||||||
JsonUtility.FromJsonOverwrite(data, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
*/
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 28bfb13cf2845d04eb5cbee51f9353d0
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,215 +0,0 @@
|
|||||||
#serverDataContainer {
|
|
||||||
margin: 4px 0 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
position: relative;
|
|
||||||
height: auto;
|
|
||||||
overflow: hidden;
|
|
||||||
padding: 8px 0 8px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.background {
|
|
||||||
position: absolute;
|
|
||||||
height: 400px;
|
|
||||||
width: 400px;
|
|
||||||
top: -10px;
|
|
||||||
right: -150px;
|
|
||||||
/* MIRROR CHANGE: disable hardcoded image path. this is inserted from the script now.
|
|
||||||
background-image: url('project://database/Assets/Edgegap/Editor/Images/logo_transparent_400_alpha25.png?fileID=21300000&guid=b7012da4ebf9008458abc3ef9a741f3c&type=3#logo_transparent_400_alpha25');
|
|
||||||
*/
|
|
||||||
-unity-background-scale-mode: scale-and-crop;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text__title {
|
|
||||||
font-size: 20px;
|
|
||||||
color: rgb(36, 194, 237);
|
|
||||||
padding-top: 8px;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
-unity-text-align: middle-center;
|
|
||||||
/* MIRROR CHANGE: disable hardcoded font path
|
|
||||||
-unity-font: url('project://database/Assets/Edgegap/Editor/Fonts/Src/BaronNeue.otf?fileID=12800000&guid=fb67205c672fbb04d829783b9f771fc9&type=3#BaronNeue');
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
.text--muted {
|
|
||||||
color: rgb(192, 192, 192);
|
|
||||||
}
|
|
||||||
|
|
||||||
.text--success {
|
|
||||||
color: rgb(144, 190, 109);
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
padding: 4px 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex--wrap {
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex--right {
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex--between {
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
#unity-text-input {
|
|
||||||
border-top-left-radius: 5px;
|
|
||||||
border-top-right-radius: 5px;
|
|
||||||
border-bottom-right-radius: 5px;
|
|
||||||
border-bottom-left-radius: 5px;
|
|
||||||
color: rgb(255, 255, 255);
|
|
||||||
border-top-width: 1px;
|
|
||||||
border-right-width: 1px;
|
|
||||||
border-bottom-width: 1px;
|
|
||||||
border-left-width: 1px;
|
|
||||||
height: 27px;
|
|
||||||
background-color: rgb(26, 26, 26);
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-edgegap {
|
|
||||||
border-top-left-radius: 3px;
|
|
||||||
border-top-right-radius: 3px;
|
|
||||||
border-bottom-right-radius: 3px;
|
|
||||||
border-bottom-left-radius: 3px;
|
|
||||||
border-top-width: 1px;
|
|
||||||
border-right-width: 1px;
|
|
||||||
border-bottom-width: 1px;
|
|
||||||
border-left-width: 1px;
|
|
||||||
border-left-color: rgba(0, 0, 0, 0.35);
|
|
||||||
border-right-color: rgba(0, 0, 0, 0.35);
|
|
||||||
border-top-color: rgba(0, 0, 0, 0.35);
|
|
||||||
border-bottom-color: rgba(0, 0, 0, 0.35);
|
|
||||||
height: 27px;
|
|
||||||
-unity-font-style: bold;
|
|
||||||
background-color: rgb(36, 76, 87);
|
|
||||||
min-width: 170px;
|
|
||||||
max-width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-edgegap:hover {
|
|
||||||
background-color: rgb(56, 96, 107);
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-purple-hover:hover {
|
|
||||||
background-color: rgb(44, 30, 210);
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-row-parent {
|
|
||||||
background-color: rgb(49, 49, 49);
|
|
||||||
border-top-color: rgb(0, 0, 0);
|
|
||||||
border-bottom-color: rgb(0, 0, 0);
|
|
||||||
border-top-width: 1px;
|
|
||||||
border-right-width: 1px;
|
|
||||||
border-bottom-width: 1px;
|
|
||||||
border-left-width: 1px;
|
|
||||||
padding-top: 10px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-edgegap {
|
|
||||||
font-size: 11px;
|
|
||||||
color: rgb(222, 222, 222);
|
|
||||||
/* MIRROR CHANGE: disable hardcoded font path
|
|
||||||
-unity-font-definition: url('project://database/Assets/Edgegap/Editor/Fonts/Spartan-Regular%20SDF.asset?fileID=11400000&guid=8b0fb2c68be09174f8ea5057b27a545c&type=2#Spartan-Regular SDF');
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-btnTxt {
|
|
||||||
font-size: 12px;
|
|
||||||
color: rgb(255, 255, 255);
|
|
||||||
-unity-font-style: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toggle > #unity-checkmark {
|
|
||||||
}
|
|
||||||
|
|
||||||
.unity-foldout > #unity-checkmark {
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-purple {
|
|
||||||
background-color: rgb(44, 30, 210);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-purple:hover {
|
|
||||||
background-color: rgb(64, 50, 230);
|
|
||||||
}
|
|
||||||
|
|
||||||
.unity-foldout {
|
|
||||||
padding-top: 10px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unity-text-field {
|
|
||||||
min-width: auto;
|
|
||||||
width: 400px;
|
|
||||||
padding-right: 5px;
|
|
||||||
white-space: normal;
|
|
||||||
-unity-text-align: middle-left;
|
|
||||||
opacity: 1;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
padding-top: 5px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unity-text-field > Label {
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-row {
|
|
||||||
background-color: rgb(37, 37, 37);
|
|
||||||
padding-top: 0;
|
|
||||||
padding-bottom: 0;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkmark-edgegap {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkmark-edgegap #unity-checkmark {
|
|
||||||
margin-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unity-text-field__input > TextElement {
|
|
||||||
color: rgb(255, 255, 255);
|
|
||||||
/* MIRROR CHANGE: disable hardcoded font path
|
|
||||||
-unity-font-definition: url('project://database/Assets/Edgegap/Editor/Fonts/UbuntuMono-R%20SDF.asset?fileID=11400000&guid=2635d61c9807d6c46bcb00a3d8645b37&type=2#UbuntuMono-R SDF');
|
|
||||||
*/
|
|
||||||
font-size: 12px;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: clip;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shakeStart {
|
|
||||||
left: 5px;
|
|
||||||
transition: left 50ms ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shakeEnd {
|
|
||||||
left: -5px;
|
|
||||||
transition: left 50ms ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.customContainerChildTxt {
|
|
||||||
padding-left: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#DeploymentConnectionUrlReadOnlyTxt > #unity-text-input {
|
|
||||||
display: flex;
|
|
||||||
visibility: visible;
|
|
||||||
background-color: rgba(0, 0, 0, 0.13);
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-purple-hover {
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b1a2e4572c5de8840ac8d98377d409ae
|
|
||||||
ScriptedImporter:
|
|
||||||
internalIDToNameTable: []
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
disableValidation: 0
|
|
@ -1,102 +0,0 @@
|
|||||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" editor-extension-mode="True">
|
|
||||||
<Style src="project://database/Assets/Edgegap/Editor/EdgegapWindow.uss?fileID=7433441132597879392&guid=b1a2e4572c5de8840ac8d98377d409ae&type=3#EdgegapWindow" />
|
|
||||||
<ui:VisualElement class="content" style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0;">
|
|
||||||
<ui:VisualElement name="HeaderHorizGroup" style="flex-grow: 1; flex-direction: row; height: 100px; background-color: rgb(37, 37, 37); left: 0;">
|
|
||||||
<ui:VisualElement name="header-logo-img" style="height: 67px; width: 100px; flex-direction: row; -unity-background-scale-mode: scale-to-fit; -unity-slice-left: 0; -unity-slice-top: 0; -unity-slice-right: 0; -unity-slice-bottom: 0; -unity-background-image-tint-color: rgb(255, 255, 255); -unity-slice-scale: 1px; align-self: center;" />
|
|
||||||
<ui:Label text="EDGEGAP" name="header-logo-txt" class="text__title" style="flex-direction: row; flex-grow: 1; color: rgb(255, 255, 255); font-size: 30px; -unity-text-align: middle-left; -unity-font-style: normal; -unity-font: initial; margin-left: 0; align-items: center; height: 74px;">
|
|
||||||
<ui:Button text="DEBUG" parse-escape-sequences="true" display-tooltip-when-elided="true" name="DebugBtn" tooltip="Hide me @ EdgegapWindowMetadata.SHOW_DEBUG_BTN" style="-unity-text-align: middle-left; white-space: normal; text-overflow: clip; justify-content: flex-start; align-self: flex-end; position: absolute; right: 0; top: 0; padding-top: 3px;" />
|
|
||||||
</ui:Label>
|
|
||||||
</ui:VisualElement>
|
|
||||||
</ui:VisualElement>
|
|
||||||
<ui:ScrollView name="BodyScrollView" style="background-color: rgb(37, 37, 37); height: 1132px; justify-content: flex-end;">
|
|
||||||
<ui:GroupBox name="ApiTokenHorizGroupBox" class="container-row-parent" style="flex-direction: row; margin-left: 0; margin-right: 0; margin-bottom: 10px; align-items: center; justify-content: flex-start; align-self: auto; padding-bottom: 0; padding-top: 0;">
|
|
||||||
<ui:TextField name="ApiTokenMaskedTxt" label="<b>API Token</b>" tooltip="No token? Click the "Get a Token" button >> Click "Verify" after entered to unlock other features" password="true" class="text-edgegap" style="padding-left: 25px; flex-grow: 0.17;" />
|
|
||||||
<ui:Button name="ApiTokenVerifyPurpleBtn" text="Verify" tooltip="On successful validation, the remaining UI will be unlocked" class="button-edgegap text-edgegap bg-purple" style="min-width: 75px; -unity-font-style: bold; visibility: visible; display: flex; overflow: hidden;" />
|
|
||||||
<ui:Button name="ApiTokenGetBtn" text="Get a Token" class="button-edgegap text-edgegap" style="-unity-font-style: bold; width: 125px; max-width: none; min-width: auto;" />
|
|
||||||
</ui:GroupBox>
|
|
||||||
<ui:VisualElement name="PostAuthContainer" usage-hints="MaskContainer" style="flex-grow: 1; transition-timing-function: ease-in; transition-duration: 0.2s;">
|
|
||||||
<ui:Foldout text="<b>Application Info</b>" name="ApplicationInfoFoldout" class="text-edgegap container-row-parent" style="margin-left: 0; -unity-font-style: normal;">
|
|
||||||
<ui:VisualElement name="ApplicationNameRow" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;">
|
|
||||||
<ui:TextField name="ApplicationNameTxt" label="Application Name" tooltip="Arbitrary name to call your app" password="false" view-data-key="ApplicationNameTxt" class="text-edgegap" />
|
|
||||||
<ui:Button name="AppLoadExistingBtn" text="Load Existing App" tooltip="Already have an existing application by this name?" class="button-edgegap text-edgegap bg-purple" style="min-width: 75px; -unity-font-style: bold; visibility: visible; display: flex; overflow: hidden;" />
|
|
||||||
</ui:VisualElement>
|
|
||||||
<ui:VisualElement name="ApplicationIconRow" class="container-row" style="flex-grow: 1;">
|
|
||||||
<ui:VisualElement name="ApplicationIconHorizGroup" class="text-edgegap" style="flex-grow: 1; flex-direction: row; align-items: center; justify-content: flex-start; align-self: stretch; width: 600px;">
|
|
||||||
<uie:ObjectField label="Application Icon" type="UnityEngine.Sprite, UnityEngine.CoreModule" name="ApplicationIconSprite" tooltip="Choose a Sprite image to use as an app icon" view-data-key="ApplicationIconSprite" style="align-items: center; justify-content: flex-start; align-self: center; width: 409px;" />
|
|
||||||
<ui:VisualElement name="SelectFileVertGroup" style="flex-grow: 0.7;">
|
|
||||||
<ui:VisualElement name="SelectFileHorizGroup" style="flex-grow: 1; flex-direction: row; align-items: center;">
|
|
||||||
<ui:Label tabindex="-1" text="Limit 200kb" parse-escape-sequences="true" display-tooltip-when-elided="true" name="SelectFileSizeLimitTooltipLabel" class="text-edgegap" style="font-size: 11px; color: rgb(147, 147, 147); -unity-text-align: upper-left;" />
|
|
||||||
</ui:VisualElement>
|
|
||||||
</ui:VisualElement>
|
|
||||||
</ui:VisualElement>
|
|
||||||
</ui:VisualElement>
|
|
||||||
<ui:VisualElement name="ApplicationCreateHorizRow" style="flex-grow: 1; flex-direction: row;">
|
|
||||||
<ui:Button name="ApplicationCreateBtn" text="Create Application" class="button-edgegap text-edgegap" style="flex-direction: row; -unity-text-align: middle-center; margin-left: 0;" />
|
|
||||||
<ui:Label tabindex="-1" text="{ApplicationCreateResultLabel}" parse-escape-sequences="true" display-tooltip-when-elided="true" name="ApplicationCreateResultLabel" class="text-edgegap" style="color: rgb(138, 238, 140); align-items: stretch; justify-content: flex-start; align-self: center;" />
|
|
||||||
</ui:VisualElement>
|
|
||||||
</ui:Foldout>
|
|
||||||
<ui:VisualElement name="ContainerRegistryFoldoutHorizRow" class="container-row-parent" style="flex-grow: 1; flex-direction: row;">
|
|
||||||
<ui:Foldout text="<b>Container Registry</b>" name="ContainerRegistryFoldout" class="text-edgegap" style="flex-grow: 1; padding-bottom: 0; padding-top: 0; padding-right: 0; padding-left: 0;">
|
|
||||||
<ui:VisualElement name="ContainerPortRow" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;">
|
|
||||||
<ui:TextField name="ContainerRegistryPortNumTxt" label="Port" tooltip="1024~49151 (Default `7770`)" value="7770" view-data-key="ContainerRegistryPortNumTxt" keyboard-type="NumberPad" class="text-edgegap" style="width: 250px;" />
|
|
||||||
<ui:VisualElement name="MIRROR_CHANGE_PORT_HARDCODED" class="MIRROR_CHANGE_PORT_HARDCODED" />
|
|
||||||
</ui:VisualElement>
|
|
||||||
<ui:VisualElement name="ContainerNewVersionTagRow" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;">
|
|
||||||
<ui:TextField name="ContainerNewVersionTagTxt" label="New Version Tag" tooltip="eg: "latest" (default), "v1.0.0", "1.0.0"" value="latest" view-data-key="ContainerNewVersionTagTxt" class="text-edgegap" />
|
|
||||||
</ui:VisualElement>
|
|
||||||
<ui:VisualElement name="ContainerUseCustomRegistryRow" view-data-key="ContainerUseCustomRegistryRow" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto; padding-top: 5px; padding-bottom: 5px;">
|
|
||||||
<ui:Toggle name="ContainerUseCustomRegistryToggle" label="Use Custom Container Registry" class="text-edgegap checkmark-edgegap" style="justify-content: flex-start; align-self: center; flex-direction: row-reverse; align-items: center; padding-left: 3px;" />
|
|
||||||
</ui:VisualElement>
|
|
||||||
<ui:VisualElement name="ContainerCustomRegistryWrapper" style="flex-grow: 1;">
|
|
||||||
<ui:VisualElement name="ContainerRegistryUrlRow" class="container-row customContainerRegistryMember" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;">
|
|
||||||
<ui:TextField name="ContainerRegistryUrlTxt" label="Registry URL" tooltip="eg: `registry.edgegap.com`, `docker.io`, `harbor.edgegap.net`" class="text-edgegap customContainerChildTxt" />
|
|
||||||
</ui:VisualElement>
|
|
||||||
<ui:VisualElement name="ContainerRepositoryRow" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;">
|
|
||||||
<ui:TextField name="ContainerImageRepositoryTxt" label="Repository" tooltip="eg: `edgegap-public/tutorial`, `mycompany-someid/mylowercaseapp-`" class="text-edgegap customContainerChildTxt" />
|
|
||||||
</ui:VisualElement>
|
|
||||||
<ui:VisualElement name="ContainerUsernameRow" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;">
|
|
||||||
<ui:TextField name="ContainerUsernameTxt" label="Username" tooltip="eg: `robot$mycompany-someid+client-push`" class="text-edgegap customContainerChildTxt" />
|
|
||||||
</ui:VisualElement>
|
|
||||||
<ui:VisualElement name="ContainerTokenRow" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;">
|
|
||||||
<ui:TextField name="ContainerTokenTxt" label="Token" tooltip="Registry pasword/token/secret (different from top-level API Token)" password="true" class="text-edgegap customContainerChildTxt" />
|
|
||||||
</ui:VisualElement>
|
|
||||||
</ui:VisualElement>
|
|
||||||
<ui:VisualElement name="ContainerBuildAndPushHorizRow" style="flex-grow: 1; flex-direction: row;">
|
|
||||||
<ui:Button name="ContainerBuildAndPushBtn" text="Build and Push" class="button-edgegap text-edgegap" style="margin-left: 0;" />
|
|
||||||
<ui:Label tabindex="-1" text="{ContainerBuildAndPushResultLabel}" parse-escape-sequences="true" display-tooltip-when-elided="true" name="ContainerBuildAndPushResultLabel" class="text-edgegap" style="color: rgb(138, 238, 140); align-items: stretch; justify-content: flex-start; align-self: center; display: none;" />
|
|
||||||
</ui:VisualElement>
|
|
||||||
</ui:Foldout>
|
|
||||||
</ui:VisualElement>
|
|
||||||
<ui:Foldout text="<b>Deployments</b>" name="DeploymentsFoldout" class="text-edgegap container-row-parent">
|
|
||||||
<ui:VisualElement name="Row" class="container-row" style="flex-grow: 1; align-items: center; flex-direction: row; justify-content: flex-start; align-self: auto;" />
|
|
||||||
<ui:GroupBox name="DeploymentsHorizGroupBox" style="flex-direction: row; justify-content: flex-start; align-items: stretch; align-self: flex-start; margin-left: 0; padding-left: 0;">
|
|
||||||
<ui:Button name="DeploymentsRefreshBtn" text="Refresh" class="button-edgegap text-edgegap" style="flex-grow: 0.5;" />
|
|
||||||
<ui:Button name="DeploymentsCreateBtn" text="Create New Deployment" class="button-edgegap text-edgegap" style="flex-grow: 0.5; max-width: 250px; min-width: 200px;" />
|
|
||||||
</ui:GroupBox>
|
|
||||||
<ui:Label tabindex="-1" text="{DeploymentsStatusLabel}" parse-escape-sequences="true" display-tooltip-when-elided="true" name="DeploymentsStatusLabel" class="text-edgegap" style="color: rgb(138, 238, 140); white-space: normal; text-overflow: ellipsis; width: 650px; display: none; margin-left: 3px;" />
|
|
||||||
<ui:GroupBox name="DeploymentsHeadersGroupBox" class="container-row-parent" style="flex-direction: row; padding-top: 6px; padding-right: 0; padding-bottom: 3px; padding-left: 0; margin-bottom: 0; align-self: auto; justify-content: flex-start; align-items: center;">
|
|
||||||
<ui:Label name="DeploymentsConnectionStatusHeaderLabel" text="Status" style="flex-grow: 0.5; -unity-text-align: upper-left; -unity-font-style: bold; width: 75px; flex-direction: column;" />
|
|
||||||
<ui:Label name="DeploymentsConnectionURLHeaderLabel" text="URL" style="flex-grow: 1; -unity-font-style: bold; align-items: auto; justify-content: flex-start; align-self: auto;" />
|
|
||||||
<ui:Label name="DeploymentsConnectionControlHeaderLabel" text="Control" style="flex-grow: 0.08; -unity-text-align: upper-left; -unity-font-style: bold; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0;" />
|
|
||||||
</ui:GroupBox>
|
|
||||||
<ui:GroupBox name="DeploymentsConnectionGroupBox" style="flex-direction: row; padding-left: 0; align-items: center; align-self: stretch; justify-content: flex-start; height: 64px;">
|
|
||||||
<ui:Label name="DeploymentsConnectionStatusLabel" text="Unknown" class="text--muted" style="flex-grow: 1; flex-direction: column; -unity-text-align: middle-left; justify-content: flex-start; align-items: center; width: 86px; margin-right: 15px;" />
|
|
||||||
<ui:VisualElement name="DeploymentConnectionUrlHorizGroup" style="flex-grow: 1; flex-direction: row; width: 304px; margin-left: 25px; margin-right: 25px; padding-right: 25px; padding-left: 25px;">
|
|
||||||
<ui:TextField picking-mode="Ignore" name="DeploymentConnectionUrlReadOnlyTxt" readonly="true" tooltip="Selectable" style="padding-left: 0; -unity-text-align: middle-center; width: 297px; align-items: center;">
|
|
||||||
<ui:Button name="DeploymentConnectionCopyUrlBtn" tooltip="Copy" class="text-edgegap bg-purple" style="min-width: 15px; visibility: visible; display: flex; overflow: hidden; width: 35px; -unity-background-scale-mode: scale-to-fit; min-height: 25px; background-color: rgb(44, 30, 210); -unity-background-image-tint-color: rgb(224, 224, 224); -unity-slice-left: 1; -unity-slice-top: 1; -unity-slice-right: 1; -unity-slice-bottom: 1; translate: -40px 0;" />
|
|
||||||
</ui:TextField>
|
|
||||||
</ui:VisualElement>
|
|
||||||
<ui:VisualElement name="DeploymentsConnectionServerStopHorizBtnHorizGroup" style="flex-grow: 1; flex-direction: column; align-items: center; justify-content: center; align-self: auto;">
|
|
||||||
<ui:Button name="DeploymentsConnectionServerStopBtn" text="Stop Server" class="button-edgegap text-edgegap" style="min-width: auto; width: 125px; max-width: none; visibility: visible; display: flex;" />
|
|
||||||
<ui:Button name="DeploymentsConnectionContainerLogsBtn" text="Container Logs" class="button-edgegap text-edgegap" style="min-width: auto; width: 125px; max-width: none; visibility: visible; display: flex;" />
|
|
||||||
</ui:VisualElement>
|
|
||||||
</ui:GroupBox>
|
|
||||||
</ui:Foldout>
|
|
||||||
<ui:VisualElement name="ServerDataContainer" />
|
|
||||||
</ui:VisualElement>
|
|
||||||
<ui:GroupBox name="FooterHorizGroup" class="container-row-parent" style="flex-direction: row; justify-content: center; align-items: stretch; align-self: auto; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-left-radius: 1px; border-top-right-radius: 1px; border-bottom-right-radius: 1px; border-bottom-left-radius: 1px; border-right-color: rgb(0, 0, 0); border-left-color: rgb(0, 0, 0); padding-right: 135px; padding-left: 150px; padding-top: 15px; padding-bottom: 15px;">
|
|
||||||
<ui:Button text="Documentation" tooltip="Opens the documentation website. The website version changes depending on the selected API environment." name="FooterDocumentationBtn" class="button-edgegap text-edgegap" style="align-items: stretch;" />
|
|
||||||
<ui:Button text="Add More Game Servers!" tooltip="Opens the documentation website. The website version changes depending on the selected API environment." name="FooterNeedMoreGameServersBtn" class="button-edgegap text-edgegap bg-purple" style="width: 220px; max-width: none; min-width: auto;" />
|
|
||||||
</ui:GroupBox>
|
|
||||||
</ui:ScrollView>
|
|
||||||
</ui:UXML>
|
|
@ -1,10 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 8f6d8a95cd8228e468ad40dbec5ca478
|
|
||||||
ScriptedImporter:
|
|
||||||
internalIDToNameTable: []
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
|
@ -1,180 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Edgegap.Editor.Api.Models;
|
|
||||||
|
|
||||||
namespace Edgegap.Editor
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Contains static metadata / options for the EdgegapWindowV2 UI.
|
|
||||||
/// - Notable:
|
|
||||||
/// * SHOW_DEBUG_BTN
|
|
||||||
/// * LOG_LEVEL
|
|
||||||
/// * DEFAULT_VERSION_TAG
|
|
||||||
/// * SKIP_SERVER_BUILD_WHEN_PUSHING
|
|
||||||
/// * SKIP_DOCKER_IMAGE_BUILD_WHEN_PUSHING
|
|
||||||
/// </summary>
|
|
||||||
public static class EdgegapWindowMetadata
|
|
||||||
{
|
|
||||||
#region Debug
|
|
||||||
/// <summary>Log Debug+, or Errors only?</summary>
|
|
||||||
public enum LogLevel
|
|
||||||
{
|
|
||||||
Debug,
|
|
||||||
Error,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set to Debug to show more logs. Default `Error`.
|
|
||||||
/// - Error level includes "potentially-intentional" (!fatal) errors logged with Debug.Log
|
|
||||||
/// - TODO: Move opt to UI?
|
|
||||||
/// </summary>
|
|
||||||
public const LogLevel LOG_LEVEL = LogLevel.Error;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set to show a debug button at the top-right for arbitrary testing.
|
|
||||||
/// Default enables groups. Default `false`.
|
|
||||||
/// </summary>
|
|
||||||
public const bool SHOW_DEBUG_BTN = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// When running a Docker-based "Build & Push" flow, skip building the Unity server binary
|
|
||||||
/// (great for testing push flow). Default false.
|
|
||||||
/// </summary>
|
|
||||||
public static readonly bool SKIP_SERVER_BUILD_WHEN_PUSHING = false; // MIRROR CHANGE: 'const' changed to 'static readonly' to avoid 'unreachable code detected' warning
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// When running a Docker-based "Build & Push" flow, skip building the Docker image
|
|
||||||
/// (great for testing registry login mechanics). Default false.
|
|
||||||
/// </summary>
|
|
||||||
public static readonly bool SKIP_DOCKER_IMAGE_BUILD_WHEN_PUSHING = false; // MIRROR CHANGE: 'const' changed to 'static readonly' to avoid 'unreachable code detected' warning
|
|
||||||
#endregion // Debug
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>Interval at which the server status is updated</summary>
|
|
||||||
public const int SERVER_STATUS_CRON_JOB_INTERVAL_MS = 10000;
|
|
||||||
public const int PORT_DEFAULT = 7770;
|
|
||||||
public const int PORT_MIN = 1024;
|
|
||||||
public const int PORT_MAX = 49151;
|
|
||||||
public const int DEPLOYMENT_AWAIT_READY_STATUS_TIMEOUT_MINS = 1;
|
|
||||||
public const int DEPLOYMENT_READY_STATUS_POLL_SECONDS = 2;
|
|
||||||
public const int DEPLOYMENT_STOP_STATUS_POLL_SECONDS = 2;
|
|
||||||
public const ProtocolType DEFAULT_PROTOCOL_TYPE = ProtocolType.UDP;
|
|
||||||
public const string READY_STATUS = "Status.READY";
|
|
||||||
|
|
||||||
public const string EDGEGAP_GET_A_TOKEN_URL = "https://app.edgegap.com/?oneClick=true";
|
|
||||||
public const string EDGEGAP_ADD_MORE_GAME_SERVERS_URL = "https://edgegap.com/resources/contact";
|
|
||||||
public const string EDGEGAP_DOC_BTN_HOW_TO_LOGIN_VIA_CLI_URL = "https://docs.edgegap.com/docs/container/edgegap-container-registry/#getting-your-credentials";
|
|
||||||
private const string DEFAULT_UTM_SOURCE_TAG = "plugin_unity";
|
|
||||||
private const string DEFAULT_UTM_MEDIUM_TAG = "servers_quickstart_plugin";
|
|
||||||
private const string DEFAULT_UTM_CONTENT_TAG = "plugin_button";
|
|
||||||
public const string DEFAULT_UTM_TAGS = "utm_source=" + DEFAULT_UTM_SOURCE_TAG +
|
|
||||||
"&utm_medium=" + DEFAULT_UTM_MEDIUM_TAG +
|
|
||||||
"&utm_content=" + DEFAULT_UTM_CONTENT_TAG;
|
|
||||||
public const string DEFAULT_VERSION_TAG = "latest";
|
|
||||||
public const string LOADING_RICH_STR = "<i>Loading...</i>";
|
|
||||||
public const string PROCESSING_RICH_STR = "<i>Processing...</i>";
|
|
||||||
public const string DEPLOY_REQUEST_RICH_STR = "<i>Requesting Deploy...</i>";
|
|
||||||
|
|
||||||
#region Colors
|
|
||||||
/// <summary>Earthy lime green</summary>
|
|
||||||
public const string SUCCESS_COLOR_HEX = "#8AEE8C";
|
|
||||||
|
|
||||||
/// <summary>Calming light orange</summary>
|
|
||||||
public const string WARN_COLOR_HEX = "#EEC58A";
|
|
||||||
|
|
||||||
/// <summary>Vivid blood orange</summary>
|
|
||||||
public const string FAIL_COLOR_HEX = "#EE9A8A";
|
|
||||||
|
|
||||||
/// <summary>Corn yellow</summary>
|
|
||||||
public const string PROCESSING_COLOR_HEX = "#EEEA8A";
|
|
||||||
|
|
||||||
public enum StatusColors
|
|
||||||
{
|
|
||||||
/// <summary>CornYellow</summary>
|
|
||||||
Processing,
|
|
||||||
|
|
||||||
/// <summary>EarthyLimeGreen</summary>
|
|
||||||
Success,
|
|
||||||
|
|
||||||
/// <summary>CalmingLightOrange</summary>
|
|
||||||
Warn,
|
|
||||||
|
|
||||||
/// <summary>VividBloodOrange</summary>
|
|
||||||
Error,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <returns>Wraps string in color rich text</returns>
|
|
||||||
public static string WrapRichTextInColor(string str, StatusColors statusColor)
|
|
||||||
{
|
|
||||||
switch (statusColor)
|
|
||||||
{
|
|
||||||
case StatusColors.Processing:
|
|
||||||
return $"<color={PROCESSING_COLOR_HEX}>{str}</color>";
|
|
||||||
case StatusColors.Success:
|
|
||||||
return $"<color={SUCCESS_COLOR_HEX}>{str}</color>";
|
|
||||||
case StatusColors.Warn:
|
|
||||||
return $"<color={WARN_COLOR_HEX}>{str}</color>";
|
|
||||||
case StatusColors.Error:
|
|
||||||
return $"<color={FAIL_COLOR_HEX}>{str}</color>";
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(statusColor), statusColor, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion // Colors
|
|
||||||
|
|
||||||
#region Player Pref Key Ids for persistence
|
|
||||||
/// <summary>Cached as base64</summary>
|
|
||||||
public const string API_TOKEN_KEY_STR = "ApiToken";
|
|
||||||
public const string DEPLOYMENT_REQUEST_ID_KEY_STR = "DeploymentRequestId";
|
|
||||||
public const string DEPLOYMENT_CONNECTION_URL_KEY_STR = "DeploymentConnectionUrlLabel";
|
|
||||||
public const string DEPLOYMENT_CONNECTION_STATUS_KEY_STR = "DeploymentsConnectionStatusLabel";
|
|
||||||
public const string CONTAINER_REGISTRY_TRANSPORT_TYPE_ENUM_KEY_STR = "ContainerRegistryProtocolTypeEnum";
|
|
||||||
#endregion // Editor Pref Key Ids for persistence
|
|
||||||
|
|
||||||
#region UI Element Ids
|
|
||||||
public const string DEBUG_BTN_ID = "DebugBtn";
|
|
||||||
public const string API_TOKEN_TXT_ID = "ApiTokenMaskedTxt";
|
|
||||||
public const string API_TOKEN_VERIFY_BTN_ID = "ApiTokenVerifyPurpleBtn";
|
|
||||||
public const string API_TOKEN_GET_BTN_ID = "ApiTokenGetBtn";
|
|
||||||
public const string POST_AUTH_CONTAINER_ID = "PostAuthContainer";
|
|
||||||
|
|
||||||
public const string APP_INFO_FOLDOUT_ID = "ApplicationInfoFoldout";
|
|
||||||
public const string APP_NAME_TXT_ID = "ApplicationNameTxt";
|
|
||||||
public const string APP_LOAD_EXISTING_BTN_ID = "AppLoadExistingBtn";
|
|
||||||
public const string APP_ICON_SPRITE_OBJ_ID = "ApplicationIconSprite";
|
|
||||||
public const string APP_CREATE_BTN_ID = "ApplicationCreateBtn";
|
|
||||||
public const string APP_CREATE_RESULT_LABEL_ID = "ApplicationCreateResultLabel";
|
|
||||||
|
|
||||||
public const string CONTAINER_REGISTRY_FOLDOUT_ID = "ContainerRegistryFoldout";
|
|
||||||
public const string CONTAINER_REGISTRY_PORT_NUM_ID = "ContainerRegistryPortNumTxt";
|
|
||||||
public const string CONTAINER_REGISTRY_TRANSPORT_TYPE_ENUM_ID = "ContainerRegistryProtocolTypeEnumField";
|
|
||||||
public const string CONTAINER_NEW_TAG_VERSION_TXT_ID = "ContainerNewVersionTagTxt";
|
|
||||||
public const string CONTAINER_USE_CUSTOM_REGISTRY_TOGGLE_ID = "ContainerUseCustomRegistryToggle";
|
|
||||||
public const string CONTAINER_CUSTOM_REGISTRY_WRAPPER_ID = "ContainerCustomRegistryWrapper";
|
|
||||||
public const string CONTAINER_REGISTRY_URL_TXT_ID = "ContainerRegistryUrlTxt";
|
|
||||||
public const string CONTAINER_IMAGE_REPOSITORY_URL_TXT_ID = "ContainerImageRepositoryTxt";
|
|
||||||
public const string CONTAINER_USERNAME_TXT_ID = "ContainerUsernameTxt";
|
|
||||||
public const string CONTAINER_TOKEN_TXT_ID = "ContainerTokenTxt";
|
|
||||||
public const string CONTAINER_BUILD_AND_PUSH_BTN_ID = "ContainerBuildAndPushBtn";
|
|
||||||
public const string CONTAINER_BUILD_AND_PUSH_RESULT_LABEL_ID = "ContainerBuildAndPushResultLabel";
|
|
||||||
|
|
||||||
public const string DEPLOYMENTS_FOLDOUT_ID = "DeploymentsFoldout";
|
|
||||||
public const string DEPLOYMENTS_REFRESH_BTN_ID = "DeploymentsRefreshBtn";
|
|
||||||
public const string DEPLOYMENTS_CREATE_BTN_ID = "DeploymentsCreateBtn";
|
|
||||||
public const string DEPLOYMENTS_STATUS_LABEL_ID = "DeploymentsStatusLabel";
|
|
||||||
public const string DEPLOYMENTS_CONTAINER_ID = "DeploymentsConnectionGroupBox";
|
|
||||||
public const string DEPLOYMENTS_CONNECTION_COPY_URL_BTN_ID = "DeploymentConnectionCopyUrlBtn";
|
|
||||||
public const string DEPLOYMENTS_CONNECTION_URL_READONLY_TXT_ID = "DeploymentConnectionUrlReadOnlyTxt"; // Dynamic
|
|
||||||
public const string DEPLOYMENTS_CONNECTION_STATUS_LABEL_ID = "DeploymentsConnectionStatusLabel"; // Dynamic
|
|
||||||
public const string DEPLOYMENTS_CONNECTION_SERVER_ACTION_STOP_BTN_ID = "DeploymentsConnectionServerStopBtn";
|
|
||||||
public const string DEPLOYMENTS_CONNECTION_CONTAINER_LOGS_BTN_ID = "DeploymentsConnectionContainerLogsBtn";
|
|
||||||
|
|
||||||
public const string FOOTER_DOCUMENTATION_BTN_ID = "FooterDocumentationBtn";
|
|
||||||
public const string FOOTER_NEED_MORE_GAME_SERVERS_BTN_ID = "FooterNeedMoreGameServersBtn";
|
|
||||||
#endregion // UI Element Ids
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//[Obsolete("Hard-coded; not from UI. TODO: Get from UI")] // MIRROR CHANGE: comment this out to avoid import warnings
|
|
||||||
public const ApiEnvironment API_ENVIRONMENT = ApiEnvironment.Console;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: c17286cfb15166442920036353163fc0
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
File diff suppressed because it is too large
Load Diff
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 1c3d4497250ad3e4aa500d4c599b30fe
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 906ea06ae52d7f641958c4777a431af5
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1 +0,0 @@
|
|||||||
Removed font files to avoid all kinds of runtime errors.
|
|
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 57002d60dd8ce46b081a0a0a25e5b52b
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 57243654a91bff64ba14f4dd51959d32
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.0 KiB |
@ -1,140 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: caa516cdb721dd143bbc8000ca78d50a
|
|
||||||
TextureImporter:
|
|
||||||
internalIDToNameTable: []
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 12
|
|
||||||
mipmaps:
|
|
||||||
mipMapMode: 0
|
|
||||||
enableMipMap: 0
|
|
||||||
sRGBTexture: 1
|
|
||||||
linearTexture: 0
|
|
||||||
fadeOut: 0
|
|
||||||
borderMipMap: 0
|
|
||||||
mipMapsPreserveCoverage: 0
|
|
||||||
alphaTestReferenceValue: 0.5
|
|
||||||
mipMapFadeDistanceStart: 1
|
|
||||||
mipMapFadeDistanceEnd: 3
|
|
||||||
bumpmap:
|
|
||||||
convertToNormalMap: 0
|
|
||||||
externalNormalMap: 0
|
|
||||||
heightScale: 0.25
|
|
||||||
normalMapFilter: 0
|
|
||||||
flipGreenChannel: 0
|
|
||||||
isReadable: 0
|
|
||||||
streamingMipmaps: 0
|
|
||||||
streamingMipmapsPriority: 0
|
|
||||||
vTOnly: 0
|
|
||||||
ignoreMipmapLimit: 0
|
|
||||||
grayScaleToAlpha: 0
|
|
||||||
generateCubemap: 6
|
|
||||||
cubemapConvolution: 0
|
|
||||||
seamlessCubemap: 0
|
|
||||||
textureFormat: 1
|
|
||||||
maxTextureSize: 2048
|
|
||||||
textureSettings:
|
|
||||||
serializedVersion: 2
|
|
||||||
filterMode: 1
|
|
||||||
aniso: 1
|
|
||||||
mipBias: 0
|
|
||||||
wrapU: 1
|
|
||||||
wrapV: 1
|
|
||||||
wrapW: 0
|
|
||||||
nPOTScale: 0
|
|
||||||
lightmap: 0
|
|
||||||
compressionQuality: 50
|
|
||||||
spriteMode: 1
|
|
||||||
spriteExtrude: 1
|
|
||||||
spriteMeshType: 1
|
|
||||||
alignment: 0
|
|
||||||
spritePivot: {x: 0.5, y: 0.5}
|
|
||||||
spritePixelsToUnits: 100
|
|
||||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
spriteGenerateFallbackPhysicsShape: 1
|
|
||||||
alphaUsage: 1
|
|
||||||
alphaIsTransparency: 1
|
|
||||||
spriteTessellationDetail: -1
|
|
||||||
textureType: 8
|
|
||||||
textureShape: 1
|
|
||||||
singleChannelComponent: 0
|
|
||||||
flipbookRows: 1
|
|
||||||
flipbookColumns: 1
|
|
||||||
maxTextureSizeSet: 0
|
|
||||||
compressionQualitySet: 0
|
|
||||||
textureFormatSet: 0
|
|
||||||
ignorePngGamma: 0
|
|
||||||
applyGammaDecoding: 0
|
|
||||||
swizzle: 50462976
|
|
||||||
cookieLightType: 0
|
|
||||||
platformSettings:
|
|
||||||
- serializedVersion: 3
|
|
||||||
buildTarget: DefaultTexturePlatform
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
- serializedVersion: 3
|
|
||||||
buildTarget: WebGL
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
- serializedVersion: 3
|
|
||||||
buildTarget: Standalone
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
- serializedVersion: 3
|
|
||||||
buildTarget: Server
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
spriteSheet:
|
|
||||||
serializedVersion: 2
|
|
||||||
sprites: []
|
|
||||||
outline: []
|
|
||||||
physicsShape: []
|
|
||||||
bones: []
|
|
||||||
spriteID: 5e97eb03825dee720800000000000000
|
|
||||||
internalID: 0
|
|
||||||
vertices: []
|
|
||||||
indices:
|
|
||||||
edges: []
|
|
||||||
weights: []
|
|
||||||
secondaryTextures: []
|
|
||||||
nameFileIdTable: {}
|
|
||||||
mipmapLimitGroupName:
|
|
||||||
pSDRemoveMatte: 0
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
Binary file not shown.
Before Width: | Height: | Size: 13 KiB |
@ -1,96 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b7012da4ebf9008458abc3ef9a741f3c
|
|
||||||
TextureImporter:
|
|
||||||
internalIDToNameTable: []
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 11
|
|
||||||
mipmaps:
|
|
||||||
mipMapMode: 0
|
|
||||||
enableMipMap: 0
|
|
||||||
sRGBTexture: 1
|
|
||||||
linearTexture: 0
|
|
||||||
fadeOut: 0
|
|
||||||
borderMipMap: 0
|
|
||||||
mipMapsPreserveCoverage: 0
|
|
||||||
alphaTestReferenceValue: 0.5
|
|
||||||
mipMapFadeDistanceStart: 1
|
|
||||||
mipMapFadeDistanceEnd: 3
|
|
||||||
bumpmap:
|
|
||||||
convertToNormalMap: 0
|
|
||||||
externalNormalMap: 0
|
|
||||||
heightScale: 0.25
|
|
||||||
normalMapFilter: 0
|
|
||||||
isReadable: 0
|
|
||||||
streamingMipmaps: 0
|
|
||||||
streamingMipmapsPriority: 0
|
|
||||||
vTOnly: 0
|
|
||||||
grayScaleToAlpha: 0
|
|
||||||
generateCubemap: 6
|
|
||||||
cubemapConvolution: 0
|
|
||||||
seamlessCubemap: 0
|
|
||||||
textureFormat: 1
|
|
||||||
maxTextureSize: 2048
|
|
||||||
textureSettings:
|
|
||||||
serializedVersion: 2
|
|
||||||
filterMode: 1
|
|
||||||
aniso: 1
|
|
||||||
mipBias: 0
|
|
||||||
wrapU: 1
|
|
||||||
wrapV: 1
|
|
||||||
wrapW: 1
|
|
||||||
nPOTScale: 0
|
|
||||||
lightmap: 0
|
|
||||||
compressionQuality: 50
|
|
||||||
spriteMode: 1
|
|
||||||
spriteExtrude: 1
|
|
||||||
spriteMeshType: 1
|
|
||||||
alignment: 0
|
|
||||||
spritePivot: {x: 0.5, y: 0.5}
|
|
||||||
spritePixelsToUnits: 100
|
|
||||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
spriteGenerateFallbackPhysicsShape: 1
|
|
||||||
alphaUsage: 1
|
|
||||||
alphaIsTransparency: 1
|
|
||||||
spriteTessellationDetail: -1
|
|
||||||
textureType: 8
|
|
||||||
textureShape: 1
|
|
||||||
singleChannelComponent: 0
|
|
||||||
flipbookRows: 1
|
|
||||||
flipbookColumns: 1
|
|
||||||
maxTextureSizeSet: 0
|
|
||||||
compressionQualitySet: 0
|
|
||||||
textureFormatSet: 0
|
|
||||||
ignorePngGamma: 0
|
|
||||||
applyGammaDecoding: 0
|
|
||||||
platformSettings:
|
|
||||||
- serializedVersion: 3
|
|
||||||
buildTarget: DefaultTexturePlatform
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
spriteSheet:
|
|
||||||
serializedVersion: 2
|
|
||||||
sprites: []
|
|
||||||
outline: []
|
|
||||||
physicsShape: []
|
|
||||||
bones: []
|
|
||||||
spriteID: 5e97eb03825dee720800000000000000
|
|
||||||
internalID: 0
|
|
||||||
vertices: []
|
|
||||||
indices:
|
|
||||||
edges: []
|
|
||||||
weights: []
|
|
||||||
secondaryTextures: []
|
|
||||||
spritePackingTag:
|
|
||||||
pSDRemoveMatte: 0
|
|
||||||
pSDShowRemoveMatteOption: 0
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d1255fab0d2789b47975aa6fda86b94b
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,71 +0,0 @@
|
|||||||
namespace Edgegap
|
|
||||||
{
|
|
||||||
public enum ApiEnvironment
|
|
||||||
{
|
|
||||||
Staging,
|
|
||||||
Console,
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ApiEnvironmentsExtensions
|
|
||||||
{
|
|
||||||
public static string GetApiUrl(this ApiEnvironment apiEnvironment)
|
|
||||||
{
|
|
||||||
string apiUrl;
|
|
||||||
|
|
||||||
switch (apiEnvironment)
|
|
||||||
{
|
|
||||||
case ApiEnvironment.Staging:
|
|
||||||
apiUrl = "https://staging-api.edgegap.com";
|
|
||||||
break;
|
|
||||||
case ApiEnvironment.Console:
|
|
||||||
apiUrl = "https://api.edgegap.com";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
apiUrl = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return apiUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetDashboardUrl(this ApiEnvironment apiEnvironment)
|
|
||||||
{
|
|
||||||
string apiUrl;
|
|
||||||
|
|
||||||
switch (apiEnvironment)
|
|
||||||
{
|
|
||||||
case ApiEnvironment.Staging:
|
|
||||||
apiUrl = "https://staging-console.edgegap.com";
|
|
||||||
break;
|
|
||||||
case ApiEnvironment.Console:
|
|
||||||
apiUrl = "https://console.edgegap.com";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
apiUrl = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return apiUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetDocumentationUrl(this ApiEnvironment apiEnvironment)
|
|
||||||
{
|
|
||||||
string apiUrl;
|
|
||||||
|
|
||||||
switch (apiEnvironment)
|
|
||||||
{
|
|
||||||
case ApiEnvironment.Staging:
|
|
||||||
apiUrl = "https://staging-docs.edgegap.com/docs/category/unity";
|
|
||||||
break;
|
|
||||||
case ApiEnvironment.Console:
|
|
||||||
apiUrl = "https://docs.edgegap.com/docs/category/unity";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
apiUrl = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return apiUrl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: dd1ad4f631934cc42b0bc025483f7ffc
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,84 +0,0 @@
|
|||||||
using IO.Swagger.Model;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Edgegap
|
|
||||||
{
|
|
||||||
public enum ServerStatus
|
|
||||||
{
|
|
||||||
NA, // Not an actual Edgegap server status. Indicates that there are no active server.
|
|
||||||
Initializing,
|
|
||||||
Seeking,
|
|
||||||
Deploying,
|
|
||||||
Ready,
|
|
||||||
Seeked,
|
|
||||||
Terminated,
|
|
||||||
Scanning,
|
|
||||||
Terminating,
|
|
||||||
Error,
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ServerStatusExtensions
|
|
||||||
{
|
|
||||||
private static string GetServerStatusLabel(this Status serverStatusResponse) => char.ToUpper(serverStatusResponse.CurrentStatus[7]) + serverStatusResponse.CurrentStatus.Substring(8).ToLower();
|
|
||||||
|
|
||||||
public static ServerStatus GetServerStatus(this Status serverStatusResponse)
|
|
||||||
{
|
|
||||||
ServerStatus serverStatus;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
serverStatus = (ServerStatus)Enum.Parse(typeof(ServerStatus), serverStatusResponse.GetServerStatusLabel());
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
Debug.LogError($"Got unexpected server status: {serverStatusResponse.CurrentStatus}. Considering the deployment to be terminated.");
|
|
||||||
serverStatus = ServerStatus.Terminated;
|
|
||||||
}
|
|
||||||
|
|
||||||
return serverStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetStatusBgClass(this ServerStatus serverStatus)
|
|
||||||
{
|
|
||||||
string statusBgClass;
|
|
||||||
|
|
||||||
switch (serverStatus)
|
|
||||||
{
|
|
||||||
case ServerStatus.NA:
|
|
||||||
case ServerStatus.Terminated:
|
|
||||||
statusBgClass = "bg--secondary"; break;
|
|
||||||
case ServerStatus.Ready:
|
|
||||||
statusBgClass = "bg--success"; break;
|
|
||||||
case ServerStatus.Error:
|
|
||||||
statusBgClass = "bg--danger"; break;
|
|
||||||
default:
|
|
||||||
statusBgClass = "bg--warning"; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return statusBgClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetLabelText(this ServerStatus serverStatus)
|
|
||||||
{
|
|
||||||
string statusLabel;
|
|
||||||
|
|
||||||
if (serverStatus == ServerStatus.NA)
|
|
||||||
{
|
|
||||||
statusLabel = "N/A";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
statusLabel = Enum.GetName(typeof(ServerStatus), serverStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
return statusLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsOneOf(this ServerStatus serverStatus, params ServerStatus[] serverStatusOptions)
|
|
||||||
{
|
|
||||||
return serverStatusOptions.Contains(serverStatus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 880f675359f40d24e99109ad46894688
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,46 +0,0 @@
|
|||||||
namespace Edgegap
|
|
||||||
{
|
|
||||||
public enum ToolState
|
|
||||||
{
|
|
||||||
Disconnected,
|
|
||||||
Connecting,
|
|
||||||
Connected, // Waiting for a deployment
|
|
||||||
Building,
|
|
||||||
Pushing,
|
|
||||||
ProcessingDeployment,
|
|
||||||
DeploymentRunning,
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class PluginStateExtensions
|
|
||||||
{
|
|
||||||
public static bool CanConnect(this ToolState currentState)
|
|
||||||
{
|
|
||||||
return currentState == ToolState.Disconnected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool CanDisconnect(this ToolState currentState)
|
|
||||||
{
|
|
||||||
return currentState == ToolState.Connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool CanStartDeployment(this ToolState currentState)
|
|
||||||
{
|
|
||||||
return currentState == ToolState.Connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool CanStopDeployment(this ToolState currentState)
|
|
||||||
{
|
|
||||||
return currentState == ToolState.DeploymentRunning;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool CanEditConnectionInfo(this ToolState currentState)
|
|
||||||
{
|
|
||||||
return currentState.CanConnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasActiveDeployment(this ToolState currentState)
|
|
||||||
{
|
|
||||||
return currentState == ToolState.ProcessingDeployment || currentState == ToolState.DeploymentRunning;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user