Decompiled source of DSPRemoteSaves v2.2.2

BepInEx/plugins/DSPRemoteSaves/DSPRemoteSaves.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("DSPRemoteSaves")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DSPRemoteSaves")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9ca0b7c9-ba48-4caa-8032-76db656201ba")]
[assembly: AssemblyFileVersion("2.2.2.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("2.2.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DSPRemoteSaves
{
	[BepInPlugin("com.aims.remotesaves", "RemoteSaves", "2.2.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInProcess("DSPGAME.exe")]
	public class DSPRemoteSaves : BaseUnityPlugin
	{
		public class AuthRequest
		{
			[JsonProperty("userName")]
			public string UserName { get; set; }

			[JsonProperty("password")]
			public string Password { get; set; }

			[JsonProperty("timestamp")]
			public long? Timestamp { get; set; }

			[JsonProperty("nonce")]
			public string Nonce { get; set; }
		}

		public class FileListRequest : AuthRequest
		{
			[JsonProperty("syncFileExtensions")]
			public List<string> SyncFileExtensions { get; set; } = new List<string>();
		}

		public class UploadInitRequest : AuthRequest
		{
			[JsonProperty("fileName")]
			public string FileName { get; set; }

			[JsonProperty("fileSize")]
			public long FileSize { get; set; }

			[JsonProperty("chunkSize")]
			public int ChunkSize { get; set; }
		}

		public class CompleteUploadRequest : AuthRequest
		{
			[JsonProperty("fileId")]
			public string FileId { get; set; }
		}

		public class FileDownloadRequest : AuthRequest
		{
			[JsonProperty("fileName")]
			public string FileName { get; set; }

			[JsonProperty("isChunk")]
			public bool IsChunk { get; set; }
		}

		public class BaseResponse
		{
			[JsonProperty("code")]
			public int Code { get; set; }

			[JsonProperty("message")]
			public string Message { get; set; }
		}

		public class FileListResponse : BaseResponse
		{
			[JsonProperty("payload")]
			public FileListPayload Payload { get; set; }
		}

		public class FileListPayload
		{
			[JsonProperty("files")]
			public List<RemoteFile> Files { get; set; } = new List<RemoteFile>();

			[JsonProperty("quotaBytes")]
			public long QuotaBytes { get; set; }

			[JsonProperty("usedBytes")]
			public long UsedBytes { get; set; }

			[JsonProperty("reservedBytes")]
			public long ReservedBytes { get; set; }
		}

		public class RemoteListing
		{
			public List<RemoteFile> Files = new List<RemoteFile>();

			public long QuotaBytes;

			public long UsedBytes;

			public long ReservedBytes;

			public bool HasQuota => QuotaBytes > 0;
		}

		public class RemoteFile
		{
			[JsonProperty("fileName")]
			public string FileName { get; set; }

			[JsonProperty("fileSize")]
			public long FileSize { get; set; }

			[JsonProperty("lastModified")]
			public long LastModified { get; set; }
		}

		public class UploadInitResponse : BaseResponse
		{
			[JsonProperty("payload")]
			public UploadInitPayload Payload { get; set; }
		}

		public class UploadInitPayload
		{
			[JsonProperty("data")]
			public UploadInitData Data { get; set; }
		}

		public class UploadInitData
		{
			[JsonProperty("fileId")]
			public string FileId { get; set; }

			[JsonProperty("chunkSize")]
			public int ChunkSize { get; set; }

			[JsonProperty("totalChunks")]
			public int TotalChunks { get; set; }

			[JsonProperty("uploadToken")]
			public string UploadToken { get; set; }
		}

		public class PublicKeyInfo
		{
			public string KeyId { get; set; }

			public string PublicKey { get; set; }
		}

		public class PublicKeyResponse : BaseResponse
		{
			[JsonProperty("payload")]
			public PublicKeyPayload Payload { get; set; }
		}

		public class PublicKeyPayload
		{
			[JsonProperty("keyId")]
			public string KeyId { get; set; }

			[JsonProperty("publicKey")]
			public string PublicKey { get; set; }

			[JsonProperty("sm2Mode")]
			public string Sm2Mode { get; set; }

			[JsonProperty("sm4Mode")]
			public string Sm4Mode { get; set; }

			[JsonProperty("serverTime")]
			public long ServerTime { get; set; }
		}

		public class UploadCompleteResponse : BaseResponse
		{
			[JsonProperty("payload")]
			public UploadCompletePayload Payload { get; set; }
		}

		public class UploadCompletePayload
		{
			[JsonProperty("nots")]
			public List<int> Nots { get; set; }

			[JsonProperty("error")]
			public ErrorInfo Error { get; set; }
		}

		public class ErrorInfo
		{
			[JsonProperty("name")]
			public string Name { get; set; }

			[JsonProperty("message")]
			public string Message { get; set; }
		}

		private class ChunkMeta
		{
			public int Index { get; set; }

			public long StartPos { get; set; }

			public int ChunkLength { get; set; }
		}

		[AttributeUsage(AttributeTargets.Property)]
		public class JsonPropertyAttribute : Attribute
		{
			public string Name { get; set; }

			public bool IgnoreNull { get; set; }

			public JsonPropertyAttribute(string name)
			{
				Name = name;
				IgnoreNull = true;
			}
		}

		public class CustomJsonSerializer
		{
			public string Serialize(object obj)
			{
				StringBuilder stringBuilder = new StringBuilder();
				SerializeValue(obj, stringBuilder, 0);
				return stringBuilder.ToString();
			}

			public T Deserialize<T>(string json) where T : new()
			{
				int index = 0;
				return (T)ParseValue(json, ref index, typeof(T));
			}

			private void SerializeValue(object value, StringBuilder sb, int depth)
			{
				if (value == null)
				{
					sb.Append("null");
					return;
				}
				Type type = value.GetType();
				if (type == typeof(string))
				{
					sb.Append("\"" + EscapeString((string)value) + "\"");
				}
				else if (type == typeof(bool))
				{
					sb.Append(((bool)value) ? "true" : "false");
				}
				else if (type.IsEnum)
				{
					sb.Append("\"" + EscapeString(value.ToString()) + "\"");
				}
				else if (type.IsPrimitive || type == typeof(decimal))
				{
					sb.Append(Convert.ToString(value, CultureInfo.InvariantCulture));
				}
				else if (IsDictionary(type))
				{
					SerializeDictionary((IDictionary)value, sb, depth);
				}
				else if (IsEnumerable(type))
				{
					SerializeArray((IEnumerable)value, sb, depth);
				}
				else
				{
					SerializeObject(value, sb, depth);
				}
			}

			private void SerializeObject(object obj, StringBuilder sb, int depth)
			{
				sb.Append("{");
				PropertyInfo[] properties = obj.GetType().GetProperties();
				bool flag = true;
				PropertyInfo[] array = properties;
				foreach (PropertyInfo propertyInfo in array)
				{
					if (propertyInfo.CanRead)
					{
						string text = propertyInfo.GetCustomAttribute<JsonPropertyAttribute>()?.Name ?? propertyInfo.Name;
						object value = propertyInfo.GetValue(obj);
						if (flag)
						{
							flag = false;
						}
						else
						{
							sb.Append(",");
						}
						sb.Append("\"" + text + "\":");
						SerializeValue(value, sb, depth + 1);
					}
				}
				sb.Append("}");
			}

			private void SerializeArray(IEnumerable collection, StringBuilder sb, int depth)
			{
				sb.Append("[");
				bool flag = true;
				foreach (object item in collection)
				{
					if (flag)
					{
						flag = false;
					}
					else
					{
						sb.Append(",");
					}
					SerializeValue(item, sb, depth + 1);
				}
				sb.Append("]");
			}

			private void SerializeDictionary(IDictionary dict, StringBuilder sb, int depth)
			{
				sb.Append("{");
				bool flag = true;
				IDictionaryEnumerator enumerator = dict.GetEnumerator();
				while (enumerator.MoveNext())
				{
					if (flag)
					{
						flag = false;
					}
					else
					{
						sb.Append(",");
					}
					object key = enumerator.Key;
					object value = enumerator.Value;
					sb.Append($"\"{key}\":");
					SerializeValue(value, sb, depth + 1);
				}
				sb.Append("}");
			}

			private object ParseValue(string json, ref int index, Type targetType)
			{
				SkipWhitespace(json, ref index);
				if (index >= json.Length)
				{
					return null;
				}
				switch (json[index])
				{
				case '{':
					return ParseObject(json, ref index, targetType);
				case '[':
					return ParseArray(json, ref index, targetType);
				case '"':
					return ParseString(json, ref index);
				default:
					if (index + 4 < json.Length && json.Substring(index, 4) == "null")
					{
						index += 4;
						return null;
					}
					return ParsePrimitive(json, ref index, targetType);
				}
			}

			private object ParseObject(string json, ref int index, Type targetType)
			{
				index++;
				object obj = Activator.CreateInstance(targetType);
				Dictionary<string, PropertyInfo> dictionary = CreatePropertyMap(targetType);
				while (index < json.Length)
				{
					SkipWhitespace(json, ref index);
					if (index >= json.Length || json[index] == '}')
					{
						break;
					}
					string key = ParseString(json, ref index);
					SkipWhitespace(json, ref index);
					if (index >= json.Length)
					{
						break;
					}
					if (json[index] != ':')
					{
						throw new FormatException("Expected colon");
					}
					index++;
					if (dictionary.TryGetValue(key, out var value) && value.CanWrite)
					{
						object value2 = ParseValue(json, ref index, value.PropertyType);
						value.SetValue(obj, value2);
					}
					else
					{
						SkipValue(json, ref index);
					}
					SkipWhitespace(json, ref index);
					if (index < json.Length && json[index] == ',')
					{
						index++;
					}
				}
				index++;
				return obj;
			}

			private Dictionary<string, PropertyInfo> CreatePropertyMap(Type type)
			{
				Dictionary<string, PropertyInfo> dictionary = new Dictionary<string, PropertyInfo>(StringComparer.OrdinalIgnoreCase);
				PropertyInfo[] properties = type.GetProperties();
				foreach (PropertyInfo propertyInfo in properties)
				{
					string key = propertyInfo.GetCustomAttribute<JsonPropertyAttribute>()?.Name ?? propertyInfo.Name;
					dictionary[key] = propertyInfo;
				}
				return dictionary;
			}

			private object ParseArray(string json, ref int index, Type targetType)
			{
				index++;
				List<object> list = new List<object>();
				Type collectionElementType = GetCollectionElementType(targetType);
				while (index < json.Length)
				{
					SkipWhitespace(json, ref index);
					if (index >= json.Length || json[index] == ']')
					{
						break;
					}
					object item = ParseValue(json, ref index, collectionElementType);
					list.Add(item);
					SkipWhitespace(json, ref index);
					if (index < json.Length && json[index] == ',')
					{
						index++;
					}
				}
				index++;
				return ConvertListToTargetType(list, targetType, collectionElementType);
			}

			private void SkipValue(string json, ref int index)
			{
				SkipWhitespace(json, ref index);
				if (index >= json.Length)
				{
					return;
				}
				char c = json[index];
				switch (c)
				{
				case '"':
					ParseString(json, ref index);
					return;
				case '[':
				case '{':
				{
					char c2 = ((c == '{') ? '}' : ']');
					int num = 0;
					while (index < json.Length)
					{
						char c3 = json[index];
						if (c3 == '"')
						{
							ParseString(json, ref index);
							continue;
						}
						if (c3 == c)
						{
							num++;
						}
						else if (c3 == c2)
						{
							num--;
							index++;
							if (num == 0)
							{
								break;
							}
							continue;
						}
						index++;
					}
					return;
				}
				}
				while (index < json.Length && !IsEndOfPrimitive(json[index]))
				{
					index++;
				}
			}

			private bool IsEnumerable(Type type)
			{
				if (typeof(IEnumerable).IsAssignableFrom(type))
				{
					return type != typeof(string);
				}
				return false;
			}

			private bool IsDictionary(Type type)
			{
				return typeof(IDictionary).IsAssignableFrom(type);
			}

			private Type GetCollectionElementType(Type collectionType)
			{
				if (collectionType.IsArray)
				{
					return collectionType.GetElementType();
				}
				if (collectionType.IsGenericType)
				{
					return collectionType.GetGenericArguments()[0];
				}
				return typeof(object);
			}

			private object ConvertListToTargetType(List<object> list, Type targetType, Type elementType)
			{
				if (targetType.IsArray)
				{
					Array array = Array.CreateInstance(elementType, list.Count);
					for (int i = 0; i < list.Count; i++)
					{
						array.SetValue(list[i], i);
					}
					return array;
				}
				if (targetType.IsGenericType)
				{
					Type type = typeof(List<>).MakeGenericType(elementType);
					object obj = Activator.CreateInstance(type);
					MethodInfo method = type.GetMethod("Add");
					{
						foreach (object item in list)
						{
							method.Invoke(obj, new object[1] { item });
						}
						return obj;
					}
				}
				return list;
			}

			private string EscapeString(string s)
			{
				if (string.IsNullOrEmpty(s))
				{
					return "";
				}
				StringBuilder stringBuilder = new StringBuilder(s.Length);
				foreach (char c in s)
				{
					switch (c)
					{
					case '\\':
						stringBuilder.Append("\\\\");
						break;
					case '"':
						stringBuilder.Append("\\\"");
						break;
					case '\n':
						stringBuilder.Append("\\n");
						break;
					case '\r':
						stringBuilder.Append("\\r");
						break;
					case '\t':
						stringBuilder.Append("\\t");
						break;
					default:
						stringBuilder.Append(c);
						break;
					}
				}
				return stringBuilder.ToString();
			}

			private string UnescapeString(string s)
			{
				if (string.IsNullOrEmpty(s))
				{
					return "";
				}
				StringBuilder stringBuilder = new StringBuilder(s.Length);
				for (int i = 0; i < s.Length; i++)
				{
					if (s[i] == '\\' && i + 1 < s.Length)
					{
						switch (s[++i])
						{
						case '\\':
							stringBuilder.Append('\\');
							break;
						case '"':
							stringBuilder.Append('"');
							break;
						case 'n':
							stringBuilder.Append('\n');
							break;
						case 'r':
							stringBuilder.Append('\r');
							break;
						case 't':
							stringBuilder.Append('\t');
							break;
						default:
							stringBuilder.Append('\\').Append(s[i]);
							break;
						}
					}
					else
					{
						stringBuilder.Append(s[i]);
					}
				}
				return stringBuilder.ToString();
			}

			private void SkipWhitespace(string json, ref int index)
			{
				while (index < json.Length && char.IsWhiteSpace(json[index]))
				{
					index++;
				}
			}

			private string ParseString(string json, ref int index)
			{
				index++;
				StringBuilder stringBuilder = new StringBuilder();
				while (index < json.Length)
				{
					char c = json[index++];
					if (c == '"')
					{
						break;
					}
					if (c == '\\' && index < json.Length)
					{
						c = json[index++];
						switch (c)
						{
						case '\\':
							stringBuilder.Append('\\');
							break;
						case '"':
							stringBuilder.Append('"');
							break;
						case 'n':
							stringBuilder.Append('\n');
							break;
						case 'r':
							stringBuilder.Append('\r');
							break;
						case 't':
							stringBuilder.Append('\t');
							break;
						default:
							stringBuilder.Append('\\').Append(c);
							break;
						}
					}
					else
					{
						stringBuilder.Append(c);
					}
				}
				return stringBuilder.ToString();
			}

			private object ParsePrimitive(string json, ref int index, Type targetType)
			{
				int num = index;
				while (index < json.Length && !IsEndOfPrimitive(json[index]))
				{
					index++;
				}
				string text = json.Substring(num, index - num);
				if (targetType == typeof(bool))
				{
					return bool.Parse(text);
				}
				if (targetType.IsEnum)
				{
					return Enum.Parse(targetType, text, ignoreCase: true);
				}
				try
				{
					return Convert.ChangeType(text, targetType, CultureInfo.InvariantCulture);
				}
				catch
				{
					throw new FormatException("Cannot convert '" + text + "' to " + targetType.Name);
				}
			}

			private bool IsEndOfPrimitive(char c)
			{
				if (c != ',' && c != '}' && c != ']')
				{
					return char.IsWhiteSpace(c);
				}
				return true;
			}
		}

		internal sealed class SavePanel
		{
			private enum SortMode
			{
				Recent,
				Name,
				Size
			}

			private enum DirectionFilter
			{
				All,
				Upload,
				Download,
				Synced
			}

			private enum DropdownKind
			{
				None,
				Sort,
				Filter
			}

			private enum TransferKind
			{
				None,
				Upload,
				Download
			}

			private enum RowStatus
			{
				Idle,
				Queued,
				Running,
				Failed
			}

			private enum RowDirection
			{
				None,
				Upload,
				Download,
				Synced
			}

			private enum ConnState
			{
				Idle,
				Connecting,
				Connected,
				Failed
			}

			private sealed class SaveRow
			{
				public readonly string FileName;

				public readonly string DisplayName;

				public string LocalPath;

				public bool LocalExists;

				public long LocalSize;

				public DateTime LocalMtimeUtc;

				public bool RemoteExists;

				public long RemoteSize;

				public long RemoteMtimeMs;

				public RemoteFile Remote;

				private int _kind;

				private int _status;

				private long _transferred;

				private long _total;

				private long _speed;

				private long _speedSampleBytes;

				private DateTime _speedSampleUtc;

				private int _merging;

				public string Error;

				private bool _syncedByUpload;

				private long _uploadedSize;

				private DateTime _uploadedLocalMtime;

				private DateTime _uploadedAtUtc;

				public CancellationTokenSource Cts;

				public TransferKind Kind => (TransferKind)Volatile.Read(in _kind);

				public RowStatus Status => (RowStatus)Volatile.Read(in _status);

				public bool IsBusy
				{
					get
					{
						RowStatus status = Status;
						if (Kind != TransferKind.None)
						{
							if (status != RowStatus.Queued)
							{
								return status == RowStatus.Running;
							}
							return true;
						}
						return false;
					}
				}

				public long Transferred => Interlocked.Read(in _transferred);

				public long Total => Interlocked.Read(in _total);

				public long Speed => Interlocked.Read(in _speed);

				public bool IsMerging => Volatile.Read(in _merging) == 1;

				public float Progress
				{
					get
					{
						long total = Total;
						if (total <= 0)
						{
							return 0f;
						}
						return Mathf.Clamp01((float)((double)Transferred / (double)total));
					}
				}

				public double EtaSeconds
				{
					get
					{
						long speed = Speed;
						if (speed <= 0)
						{
							return -1.0;
						}
						long num = Total - Transferred;
						if (num <= 0)
						{
							return 0.0;
						}
						return (double)num / (double)speed;
					}
				}

				public long MaxSize => Math.Max(LocalSize, RemoteSize);

				public DateTime RecentUtc
				{
					get
					{
						DateTime dateTime = FromUnixMs(RemoteMtimeMs);
						if (!(LocalMtimeUtc > dateTime))
						{
							return dateTime;
						}
						return LocalMtimeUtc;
					}
				}

				public RowDirection Direction
				{
					get
					{
						if (LocalExists && RemoteExists)
						{
							if (_syncedByUpload && LocalSize == RemoteSize && RemoteMtimeMs > 0 && Math.Abs(RemoteMtimeMs - ToUnixMs(_uploadedAtUtc)) <= 600000)
							{
								return RowDirection.Synced;
							}
							if (LocalSize == RemoteSize && TimeClose)
							{
								return RowDirection.Synced;
							}
							long num = ToUnixMs(LocalMtimeUtc);
							if (RemoteMtimeMs <= 0 || RemoteMtimeMs < num)
							{
								return RowDirection.Upload;
							}
							return RowDirection.Download;
						}
						if (LocalExists)
						{
							return RowDirection.Upload;
						}
						if (RemoteExists)
						{
							return RowDirection.Download;
						}
						return RowDirection.None;
					}
				}

				private bool TimeClose
				{
					get
					{
						if (RemoteMtimeMs <= 0)
						{
							return true;
						}
						return Math.Abs(RemoteMtimeMs - ToUnixMs(LocalMtimeUtc)) <= 2000;
					}
				}

				public SaveRow(RemoteFile remote, FileInfo local)
				{
					DisplayName = MakeDisplayName(FileName = remote?.FileName ?? local?.Name ?? "unknown.dsv");
					LocalPath = local?.FullName;
					if (remote != null)
					{
						Remote = remote;
						RemoteExists = true;
						RemoteSize = remote.FileSize;
						RemoteMtimeMs = remote.LastModified;
					}
					if (local == null)
					{
						return;
					}
					try
					{
						if (local.Exists)
						{
							LocalExists = true;
							LocalSize = local.Length;
							LocalMtimeUtc = local.LastWriteTimeUtc;
							LocalPath = local.FullName;
						}
					}
					catch
					{
						LocalExists = false;
					}
				}

				public void Begin(TransferKind kind)
				{
					Error = null;
					Volatile.Write(ref _merging, 0);
					Interlocked.Exchange(ref _transferred, 0L);
					Interlocked.Exchange(ref _total, (kind == TransferKind.Upload) ? LocalSize : RemoteSize);
					Interlocked.Exchange(ref _speed, 0L);
					_speedSampleBytes = 0L;
					_speedSampleUtc = DateTime.UtcNow;
					Cts?.Dispose();
					Cts = new CancellationTokenSource();
					Volatile.Write(ref _status, 1);
					Volatile.Write(ref _kind, (int)kind);
				}

				public void MarkRunning()
				{
					Volatile.Write(ref _status, 2);
					_speedSampleBytes = Transferred;
					_speedSampleUtc = DateTime.UtcNow;
				}

				public void BeginMerging()
				{
					Volatile.Write(ref _merging, 1);
				}

				public void AddProgress(long delta)
				{
					Interlocked.Add(ref _transferred, delta);
				}

				public void FillProgress()
				{
					long total = Total;
					if (total > 0)
					{
						Interlocked.Exchange(ref _transferred, total);
					}
				}

				public void UpdateSpeed()
				{
					DateTime utcNow = DateTime.UtcNow;
					double totalSeconds = (utcNow - _speedSampleUtc).TotalSeconds;
					if (!(totalSeconds < 0.4))
					{
						long transferred = Transferred;
						double num = (double)(transferred - _speedSampleBytes) / Math.Max(0.001, totalSeconds);
						long speed = Speed;
						double val = ((speed <= 0) ? num : ((double)speed * 0.6 + num * 0.4));
						Interlocked.Exchange(ref _speed, (long)Math.Max(0.0, val));
						_speedSampleBytes = transferred;
						_speedSampleUtc = utcNow;
					}
				}

				public void Complete()
				{
					Volatile.Write(ref _merging, 0);
					Volatile.Write(ref _status, 0);
					Volatile.Write(ref _kind, 0);
					Error = null;
					Interlocked.Exchange(ref _speed, 0L);
				}

				public void Fail(string message)
				{
					Volatile.Write(ref _merging, 0);
					Error = message;
					Volatile.Write(ref _status, 3);
					Volatile.Write(ref _kind, 0);
					Interlocked.Exchange(ref _speed, 0L);
				}

				public void Canceled()
				{
					Volatile.Write(ref _merging, 0);
					Error = null;
					Volatile.Write(ref _status, 0);
					Volatile.Write(ref _kind, 0);
					Interlocked.Exchange(ref _speed, 0L);
				}

				public void End()
				{
					Volatile.Write(ref _merging, 0);
					Volatile.Write(ref _kind, 0);
					if (Volatile.Read(in _status) == 2)
					{
						Volatile.Write(ref _status, 0);
					}
					try
					{
						Cts?.Dispose();
					}
					catch
					{
					}
					Cts = null;
				}

				public void MarkUploaded()
				{
					RefreshLocal();
					if (LocalExists)
					{
						RemoteExists = true;
						RemoteSize = LocalSize;
						RemoteMtimeMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
						_uploadedSize = LocalSize;
						_uploadedLocalMtime = LocalMtimeUtc;
						_uploadedAtUtc = DateTime.UtcNow;
						_syncedByUpload = true;
					}
				}

				public void UpdateFrom(RemoteFile remote, FileInfo local)
				{
					Remote = remote;
					RemoteExists = remote != null;
					RemoteSize = remote?.FileSize ?? 0;
					RemoteMtimeMs = remote?.LastModified ?? 0;
					LocalExists = false;
					LocalSize = 0L;
					LocalMtimeUtc = DateTime.MinValue;
					if (local != null)
					{
						try
						{
							if (local.Exists)
							{
								LocalExists = true;
								LocalSize = local.Length;
								LocalMtimeUtc = local.LastWriteTimeUtc;
								LocalPath = local.FullName;
							}
						}
						catch
						{
							LocalExists = false;
						}
					}
					if (_syncedByUpload && (!LocalExists || !RemoteExists || LocalSize != _uploadedSize || LocalMtimeUtc != _uploadedLocalMtime))
					{
						_syncedByUpload = false;
					}
				}

				public void ApplyRemote(RemoteFile remote)
				{
					Remote = remote;
					RemoteExists = remote != null;
					RemoteSize = remote?.FileSize ?? 0;
					RemoteMtimeMs = remote?.LastModified ?? 0;
				}

				public void RefreshLocal()
				{
					if (string.IsNullOrEmpty(LocalPath))
					{
						return;
					}
					try
					{
						FileInfo fileInfo = new FileInfo(LocalPath);
						if (!fileInfo.Exists)
						{
							LocalExists = false;
							LocalSize = 0L;
							LocalMtimeUtc = DateTime.MinValue;
						}
						else
						{
							LocalExists = true;
							LocalSize = fileInfo.Length;
							LocalMtimeUtc = fileInfo.LastWriteTimeUtc;
						}
					}
					catch
					{
					}
				}
			}

			private const float PanelW = 1160f;

			private const float PanelH = 700f;

			private const float HeaderH = 44f;

			private const float ToolbarH = 40f;

			private const float TableHeadH = 26f;

			private const float FooterH = 44f;

			private const float RowH = 58f;

			private const float ProgressH = 30f;

			private const float ErrorH = 24f;

			private const float ListY = 110f;

			private const float ListH = 546f;

			private const float Radius = 10f;

			private const float SearchX = 946f;

			private const float SearchY = 51f;

			private const float SearchW = 198f;

			private const float SearchH = 26f;

			private const string SearchControl = "dsprs-search";

			private Color PanelBg = C(12, 33, 47, 0.45f);

			private Color HeaderBg = C(27, 62, 84, 0.59f);

			private Color ToolbarBg = C(17, 44, 59, 0.57f);

			private Color TableHeadBg = C(15, 38, 52, 0.57f);

			private Color FooterBg = C(15, 38, 52, 0.57f);

			private Color RowBgA = C(22, 49, 64, 0.18f);

			private Color RowBgB = C(18, 42, 56, 0.1f);

			private Color RowHover = C(34, 72, 93, 0.28f);

			private Color Separator = C(35, 68, 87, 0.27f);

			private Color Border = C(48, 84, 105, 0.5f);

			private static readonly Color TextPrimary = C(232, 241, 246, 1f);

			private static readonly Color TextSecondary = C(154, 178, 192, 1f);

			private static readonly Color TextDim = C(103, 128, 143, 1f);

			private static readonly Color TextFaint = C(82, 105, 119, 1f);

			private static readonly Color AccentCyan = C(121, 214, 232, 1f);

			private static readonly Color AccentAmber = C(233, 193, 124, 1f);

			private static readonly Color AccentGreen = C(126, 214, 168, 1f);

			private static readonly Color AccentRed = C(226, 132, 116, 1f);

			private static readonly Color BtnUploadBg = C(18, 62, 80, 0.95f);

			private static readonly Color BtnUploadBorder = C(79, 195, 221, 0.9f);

			private static readonly Color BtnDownloadBg = C(69, 53, 31, 0.95f);

			private static readonly Color BtnDownloadBorder = C(217, 174, 106, 0.9f);

			private static readonly Color ChipBg = C(18, 54, 74, 0.9f);

			private static readonly Color ChipBorder = C(46, 106, 133, 0.9f);

			private static readonly Color ProgressTrack = C(32, 59, 76, 0.9f);

			private static readonly Color ProgressUp = C(97, 203, 224, 1f);

			private static readonly Color ProgressDown = C(227, 182, 120, 1f);

			private static readonly Color MergeAccent = C(169, 139, 255, 1f);

			private static readonly Color MergeText = C(206, 192, 250, 1f);

			private static readonly Color MergeRowBg = C(23, 26, 52, 0.9f);

			private readonly DSPRemoteSaves _plugin;

			private readonly SemaphoreSlim _uploadSlots;

			private readonly SemaphoreSlim _downloadSlots;

			private readonly List<SaveRow> _rows = new List<SaveRow>();

			private readonly List<SaveRow> _view = new List<SaveRow>();

			private bool _visible;

			private bool _loading;

			private bool _refreshing;

			private ConnState _connection;

			private string _listError;

			private string _search = string.Empty;

			private SortMode _sort;

			private DirectionFilter _filter;

			private DropdownKind _openDropdown;

			private float _scroll;

			private float _contentHeight;

			private DateTime _nextAutoRefreshUtc = DateTime.MaxValue;

			private DateTime _scheduledRefreshUtc = DateTime.MaxValue;

			private long _quotaBytes;

			private long _usedBytes;

			private long _reservedBytes;

			private bool _hasQuota;

			private bool _cursorCaptured;

			private bool _cursorVisible;

			private CursorLockMode _cursorLock;

			private Behaviour _savedInputModule;

			private bool _savedInputModuleEnabled;

			private bool _inputSuppressed;

			private float _nextInputSuppressAttempt;

			private Font _font;

			private float _scale = 1f;

			private float _builtScale = -1f;

			private float _px;

			private float _py;

			private float _opacityBase = -1f;

			private Vector2 _lastMouseGui;

			private float _offsetX;

			private float _offsetY;

			private bool _dragging;

			private Vector2 _dragStartMouse;

			private Vector2 _dragStartOffset;

			private readonly Dictionary<long, Texture2D> _circleCache = new Dictionary<long, Texture2D>();

			private Texture2D _white;

			private Texture2D _logo;

			private Texture2D _magnifier;

			private Texture2D _shine;

			private Texture2D _searchBgTex;

			private GUIStyle _styleTitle;

			private GUIStyle _styleSubtitle;

			private GUIStyle _styleRowName;

			private GUIStyle _styleMetaRight;

			private GUIStyle _styleRight;

			private GUIStyle _styleSmallRight;

			private GUIStyle _styleSmallPrimary;

			private GUIStyle _styleDimSmall;

			private GUIStyle _styleTableHead;

			private GUIStyle _styleTableHeadRight;

			private GUIStyle _styleTableHeadCenter;

			private GUIStyle _styleStatus;

			private GUIStyle _styleLegend;

			private GUIStyle _styleButton;

			private GUIStyle _styleProgress;

			private GUIStyle _styleClose;

			private GUIStyle _stylePlaceholder;

			private GUIStyle _styleEmptyTitle;

			private GUIStyle _styleEmptySub;

			private GUIStyle _styleSearch;

			private GUIStyle _styleBlank;

			private GUIStyle _cmHint;

			private GUIStyle _cmDot;

			private bool _scrollDragging;

			private float _scrollDragOffset;

			private bool _inGroup;

			private Vector2 _groupMouse;

			private bool _depthRaised;

			private static bool _cmProbed;

			private static bool _cmAvailable;

			private static Type _cmAttrType;

			private string _lastErrorShort;

			private bool _blockInput;

			private readonly Dictionary<long, Texture2D[]> _cornerSets = new Dictionary<long, Texture2D[]>();

			internal static bool ConfigurationManagerAvailable
			{
				get
				{
					ProbeConfigurationManager();
					return _cmAvailable;
				}
			}

			internal bool HasActiveTransfers
			{
				get
				{
					for (int i = 0; i < _rows.Count; i++)
					{
						if (_rows[i].IsBusy)
						{
							return true;
						}
					}
					return false;
				}
			}

			private string ConfigSummary => _connection switch
			{
				ConnState.Connecting => "正在连接 " + ServerDisplay + "…", 
				ConnState.Connected => $"已连接 · {ServerDisplay} · {_rows.Count} 个存档" + (HasActiveTransfers ? $" · 传输中 {CountBusy()}" : ""), 
				ConnState.Failed => "未连接" + (string.IsNullOrEmpty(_lastErrorShort) ? "" : (" · " + Trim(_lastErrorShort, 26))), 
				_ => "云存档同步:待加载", 
			};

			private string ServerDisplay
			{
				get
				{
					HttpClient httpClient = _plugin.httpClient;
					Uri uri = ((httpClient != null) ? httpClient.BaseAddress : null);
					if (uri == null)
					{
						return "未连接";
					}
					if (!uri.IsDefaultPort)
					{
						return uri.Host + ":" + uri.Port;
					}
					return uri.Host;
				}
			}

			private string StatusLine => _connection switch
			{
				ConnState.Connecting => "连接中 · " + ServerDisplay, 
				ConnState.Connected => "已连接 · " + ServerDisplay, 
				ConnState.Failed => "未连接 · " + ServerDisplay, 
				_ => "未连接", 
			};

			private Color StatusColor => (Color)(_connection switch
			{
				ConnState.Connected => AccentGreen, 
				ConnState.Connecting => AccentAmber, 
				ConnState.Failed => AccentRed, 
				_ => TextFaint, 
			});

			private string SortLabel => _sort switch
			{
				SortMode.Name => "名称", 
				SortMode.Size => "大小", 
				_ => "最近修改", 
			};

			private string FilterLabel => _filter switch
			{
				DirectionFilter.Upload => "待上传", 
				DirectionFilter.Download => "待下载", 
				DirectionFilter.Synced => "已一致", 
				_ => "全部", 
			};

			private Vector2 Pointer
			{
				get
				{
					//IL_0014: Unknown result type (might be due to invalid IL or missing references)
					//IL_000d: Unknown result type (might be due to invalid IL or missing references)
					if (!_inGroup)
					{
						return Event.current.mousePosition;
					}
					return _groupMouse;
				}
			}

			private static void ProbeConfigurationManager()
			{
				if (_cmProbed)
				{
					return;
				}
				_cmProbed = true;
				try
				{
					Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
					for (int i = 0; i < assemblies.Length; i++)
					{
						Type type = assemblies[i].GetType("ConfigurationManager.ConfigurationManagerAttributes", throwOnError: false);
						if (type != null)
						{
							_cmAttrType = type;
							_cmAvailable = true;
							return;
						}
					}
					Type type2 = Assembly.Load("BepInEx.ConfigurationManager").GetType("ConfigurationManager.ConfigurationManagerAttributes", throwOnError: false);
					if (type2 != null)
					{
						_cmAttrType = type2;
						_cmAvailable = true;
					}
				}
				catch
				{
					_cmAvailable = false;
				}
			}

			internal static object CreateConfigurationManagerAttributes(Action<ConfigEntryBase> drawer)
			{
				ProbeConfigurationManager();
				if (!_cmAvailable || _cmAttrType == null)
				{
					return null;
				}
				try
				{
					object? obj = Activator.CreateInstance(_cmAttrType);
					SetMember(obj, "CustomDrawer", drawer);
					SetMember(obj, "DispName", "云存档同步面板");
					SetMember(obj, "Order", -100);
					SetMember(obj, "Description", "打开游戏内云存档同步面板,手动选择要上传或下载的存档");
					return obj;
				}
				catch
				{
					return null;
				}
			}

			private static void SetMember(object target, string name, object value)
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public;
				FieldInfo field = _cmAttrType.GetField(name, bindingAttr);
				if (field != null)
				{
					field.SetValue(target, Coerce(value, field.FieldType));
					return;
				}
				PropertyInfo property = _cmAttrType.GetProperty(name, bindingAttr);
				if (property != null && property.CanWrite)
				{
					property.SetValue(target, Coerce(value, property.PropertyType));
				}
			}

			private static object Coerce(object value, Type type)
			{
				Type type2 = Nullable.GetUnderlyingType(type) ?? type;
				if (value == null || type2.IsInstanceOfType(value))
				{
					return value;
				}
				return Convert.ChangeType(value, type2, CultureInfo.InvariantCulture);
			}

			public SavePanel(DSPRemoteSaves plugin)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0053: Unknown result type (might be due to invalid IL or missing references)
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: Unknown result type (might be due to invalid IL or missing references)
				//IL_0095: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
				_plugin = plugin;
				_uploadSlots = new SemaphoreSlim(Math.Max(1, plugin.configMaxParallelUploadCount.Value));
				_downloadSlots = new SemaphoreSlim(Math.Max(1, plugin.configMaxParallelDownloadCount.Value));
			}

			internal void Tick()
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				if (Input.GetKeyDown(_plugin.configPanelHotkey.Value))
				{
					if (_visible)
					{
						Close();
					}
					else
					{
						Open();
					}
				}
				if (!_visible)
				{
					return;
				}
				if (Input.GetKeyDown((KeyCode)27))
				{
					Close();
					return;
				}
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)0;
				for (int i = 0; i < _rows.Count; i++)
				{
					if (_rows[i].Status == RowStatus.Running)
					{
						_rows[i].UpdateSpeed();
					}
				}
				DateTime utcNow = DateTime.UtcNow;
				if (_scheduledRefreshUtc != DateTime.MaxValue && utcNow >= _scheduledRefreshUtc)
				{
					_scheduledRefreshUtc = DateTime.MaxValue;
					Refresh();
				}
				if (_plugin.configAutoRefreshSeconds.Value > 0 && !_refreshing && !HasActiveTransfers && utcNow >= _nextAutoRefreshUtc && !MouseOverPanel())
				{
					Refresh();
				}
				Input.ResetInputAxes();
				if (_inputSuppressed && (Object)(object)_savedInputModule == (Object)null && Time.unscaledTime >= _nextInputSuppressAttempt)
				{
					_nextInputSuppressAttempt = Time.unscaledTime + 3f;
					SuppressGameInput();
				}
			}

			private void SuppressGameInput()
			{
				if (_inputSuppressed && (Object)(object)_savedInputModule != (Object)null)
				{
					return;
				}
				_inputSuppressed = true;
				try
				{
					Type type = FindLoadedType("UnityEngine.EventSystems.EventSystem");
					if (type == null)
					{
						return;
					}
					object obj = type.GetProperty("current", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
					if (obj != null)
					{
						object? obj2 = type.GetProperty("currentInputModule")?.GetValue(obj);
						Behaviour val = (Behaviour)((obj2 is Behaviour) ? obj2 : null);
						if (!((Object)(object)val == (Object)null))
						{
							_savedInputModule = val;
							_savedInputModuleEnabled = val.enabled;
							val.enabled = false;
						}
					}
				}
				catch
				{
				}
			}

			private void RestoreGameInput()
			{
				if (!_inputSuppressed)
				{
					return;
				}
				_inputSuppressed = false;
				try
				{
					if ((Object)(object)_savedInputModule != (Object)null)
					{
						_savedInputModule.enabled = _savedInputModuleEnabled;
					}
				}
				catch
				{
				}
				_savedInputModule = null;
			}

			private static Type FindLoadedType(string fullName)
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				for (int i = 0; i < assemblies.Length; i++)
				{
					try
					{
						Type type = assemblies[i].GetType(fullName, throwOnError: false);
						if (type != null)
						{
							return type;
						}
					}
					catch
					{
					}
				}
				return null;
			}

			internal void Open()
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				if (!_visible)
				{
					_visible = true;
					_cursorVisible = Cursor.visible;
					_cursorLock = Cursor.lockState;
					_cursorCaptured = true;
					_scroll = 0f;
					_openDropdown = DropdownKind.None;
					GameInputGuard.Active = true;
					SuppressGameInput();
					Refresh();
				}
			}

			internal void Close()
			{
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				if (_visible)
				{
					_visible = false;
					_openDropdown = DropdownKind.None;
					GameInputGuard.Active = false;
					RestoreGameInput();
					if (_cursorCaptured)
					{
						Cursor.visible = _cursorVisible;
						Cursor.lockState = _cursorLock;
						_cursorCaptured = false;
					}
				}
			}

			internal void Shutdown()
			{
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				CancelAll();
				_visible = false;
				GameInputGuard.Active = false;
				RestoreGameInput();
				if (_cursorCaptured)
				{
					Cursor.visible = _cursorVisible;
					Cursor.lockState = _cursorLock;
					_cursorCaptured = false;
				}
			}

			internal void DrawConfigEntry(ConfigEntryBase entry)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Expected O, but got Unknown
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				//IL_0092: Expected O, but got Unknown
				//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
				//IL_0122: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
				if (_cmDot == null)
				{
					Font font = EnsureFont();
					_cmDot = new GUIStyle(GUI.skin.label)
					{
						font = font,
						fontSize = Mathf.Max(10, GUI.skin.label.fontSize)
					};
					_cmHint = new GUIStyle(GUI.skin.label)
					{
						font = font,
						fontSize = Mathf.Max(9, GUI.skin.label.fontSize - 2),
						wordWrap = false,
						clipping = (TextClipping)1
					};
					_cmHint.normal.textColor = new Color(0.58f, 0.64f, 0.69f, 1f);
				}
				GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				Color color = ((_connection == ConnState.Connected) ? AccentGreen : ((_connection == ConnState.Failed) ? AccentRed : AccentAmber));
				Color color2 = GUI.color;
				GUI.color = color;
				GUILayout.Label("●", _cmDot, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(14f) });
				GUI.color = color2;
				GUILayout.Label(ConfigSummary, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				if (GUILayout.Button(_visible ? "面板已打开" : "打开面板", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(96f) }))
				{
					if (_visible)
					{
						Close();
					}
					else
					{
						Open();
					}
				}
				if (GUILayout.Button("刷新", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(52f) }))
				{
					Refresh();
				}
				GUILayout.EndHorizontal();
				GUILayout.Label($"快捷键 {_plugin.configPanelHotkey.Value} · 本地 {CountLocal()} · 云端 {CountRemote()} · 传输中 {CountBusy()}", _cmHint, Array.Empty<GUILayoutOption>());
				GUILayout.EndVertical();
			}

			private int CountLocal()
			{
				int num = 0;
				for (int i = 0; i < _rows.Count; i++)
				{
					if (_rows[i].LocalExists)
					{
						num++;
					}
				}
				return num;
			}

			private int CountRemote()
			{
				int num = 0;
				for (int i = 0; i < _rows.Count; i++)
				{
					if (_rows[i].RemoteExists)
					{
						num++;
					}
				}
				return num;
			}

			private int CountBusy()
			{
				int num = 0;
				for (int i = 0; i < _rows.Count; i++)
				{
					if (_rows[i].IsBusy)
					{
						num++;
					}
				}
				return num;
			}

			private async void Refresh()
			{
				if (_refreshing)
				{
					return;
				}
				_lastErrorShort = null;
				if (!_plugin.PrepareConnection(out var error))
				{
					_connection = ConnState.Failed;
					_listError = error;
					_lastErrorShort = error;
					_loading = false;
					_nextAutoRefreshUtc = DateTime.UtcNow.AddSeconds(5.0);
					return;
				}
				_refreshing = true;
				_loading = true;
				_listError = null;
				_connection = ConnState.Connecting;
				try
				{
					Task<RemoteListing> remoteFileList = _plugin.GetRemoteFileList();
					Dictionary<string, FileInfo> local = _plugin.GetLocalFileIndex();
					RemoteListing remoteListing = await remoteFileList;
					if (remoteListing == null)
					{
						_connection = ConnState.Failed;
						_listError = "无法获取云端存档列表" + (string.IsNullOrEmpty(_plugin.LastServerError) ? "" : (":" + Trim(_plugin.LastServerError, 40))) + "(详见 BepInEx 日志)";
						_lastErrorShort = "列表获取失败";
						_nextAutoRefreshUtc = DateTime.UtcNow.AddSeconds(15.0);
					}
					else
					{
						RebuildRows(remoteListing, local);
						ApplyQuota(remoteListing);
						_connection = ConnState.Connected;
						_nextAutoRefreshUtc = DateTime.UtcNow.AddSeconds(Math.Max(10, _plugin.configAutoRefreshSeconds.Value));
					}
				}
				catch (Exception ex)
				{
					_connection = ConnState.Failed;
					_listError = ShortError(ex);
					_lastErrorShort = _listError;
					_nextAutoRefreshUtc = DateTime.UtcNow.AddSeconds(15.0);
					((BaseUnityPlugin)_plugin).Logger.LogError((object)("刷新云存档列表失败: " + _plugin.FormatException(ex)));
				}
				finally
				{
					_refreshing = false;
					_loading = false;
				}
			}

			private void ApplyQuota(RemoteListing listing)
			{
				_hasQuota = listing.HasQuota;
				_quotaBytes = listing.QuotaBytes;
				_usedBytes = listing.UsedBytes;
				_reservedBytes = listing.ReservedBytes;
			}

			private void RebuildRows(RemoteListing listing, Dictionary<string, FileInfo> local)
			{
				Dictionary<string, SaveRow> dictionary = new Dictionary<string, SaveRow>(StringComparer.OrdinalIgnoreCase);
				for (int i = 0; i < _rows.Count; i++)
				{
					dictionary[_rows[i].FileName] = _rows[i];
				}
				Dictionary<string, RemoteFile> dictionary2 = new Dictionary<string, RemoteFile>(StringComparer.OrdinalIgnoreCase);
				foreach (RemoteFile file in listing.Files)
				{
					if (file != null && !string.IsNullOrEmpty(file.FileName))
					{
						dictionary2[file.FileName] = file;
					}
				}
				HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
				foreach (string key in dictionary2.Keys)
				{
					hashSet.Add(key);
				}
				foreach (string key2 in local.Keys)
				{
					hashSet.Add(key2);
				}
				List<SaveRow> list = new List<SaveRow>(hashSet.Count);
				foreach (string item in hashSet)
				{
					dictionary2.TryGetValue(item, out var value);
					local.TryGetValue(item, out var value2);
					if (dictionary.TryGetValue(item, out var value3))
					{
						if (!value3.IsBusy)
						{
							value3.UpdateFrom(value, value2);
						}
						list.Add(value3);
					}
					else
					{
						list.Add(new SaveRow(value, value2));
					}
				}
				_rows.Clear();
				_rows.AddRange(list);
				RebuildView();
			}

			private void RebuildView()
			{
				IEnumerable<SaveRow> source = _rows;
				if (!string.IsNullOrEmpty(_search))
				{
					string needle = _search.Trim();
					source = source.Where((SaveRow r) => r.DisplayName.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0 || r.FileName.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0);
				}
				switch (_filter)
				{
				case DirectionFilter.Upload:
					source = source.Where((SaveRow r) => r.Direction == RowDirection.Upload);
					break;
				case DirectionFilter.Download:
					source = source.Where((SaveRow r) => r.Direction == RowDirection.Download);
					break;
				case DirectionFilter.Synced:
					source = source.Where((SaveRow r) => r.Direction == RowDirection.Synced);
					break;
				}
				source = _sort switch
				{
					SortMode.Name => source.OrderBy<SaveRow, string>((SaveRow r) => r.DisplayName, StringComparer.CurrentCultureIgnoreCase), 
					SortMode.Size => source.OrderByDescending((SaveRow r) => r.MaxSize), 
					_ => source.OrderByDescending((SaveRow r) => r.RecentUtc), 
				};
				_view.Clear();
				_view.AddRange(source);
			}

			private void ScheduleRefresh(float seconds)
			{
				_scheduledRefreshUtc = DateTime.UtcNow.AddSeconds(seconds);
			}

			private void StartTransfer(SaveRow row, TransferKind kind)
			{
				if (row != null && !row.IsBusy && (kind != TransferKind.Upload || row.LocalExists) && (kind != TransferKind.Download || row.RemoteExists))
				{
					if (!_plugin.PrepareConnection(out var error))
					{
						row.Fail(error);
						return;
					}
					row.Begin(kind);
					RunTransferAsync(row, kind);
				}
			}

			private async Task RunTransferAsync(SaveRow row, TransferKind kind)
			{
				DateTime started = DateTime.UtcNow;
				CancellationToken token = row.Cts.Token;
				SemaphoreSlim slots = ((kind == TransferKind.Upload) ? _uploadSlots : _downloadSlots);
				bool slotTaken = false;
				try
				{
					await slots.WaitAsync(token);
					slotTaken = true;
					row.MarkRunning();
					if (kind == TransferKind.Upload)
					{
						DateTime mtimeBefore = row.LocalMtimeUtc;
						try
						{
							if (File.Exists(row.LocalPath))
							{
								mtimeBefore = File.GetLastWriteTimeUtc(row.LocalPath);
							}
						}
						catch
						{
						}
						if (!(await _plugin.UploadSingleFile(row.LocalPath, row.AddProgress, row.BeginMerging, token)))
						{
							if (!token.IsCancellationRequested)
							{
								row.Fail(string.IsNullOrEmpty(_plugin.LastServerError) ? "上传失败,详见 BepInEx 日志" : ("上传失败:" + Trim(_plugin.LastServerError, 52)));
							}
							return;
						}
						row.FillProgress();
						RemoteListing remoteListing = await _plugin.GetRemoteFileList();
						bool flag = false;
						try
						{
							flag = File.Exists(row.LocalPath) && File.GetLastWriteTimeUtc(row.LocalPath) == mtimeBefore;
						}
						catch
						{
						}
						RemoteFile remoteFile = remoteListing?.Files?.FirstOrDefault((RemoteFile f) => string.Equals(f.FileName, row.FileName, StringComparison.OrdinalIgnoreCase));
						if (remoteFile != null)
						{
							try
							{
								if (flag && remoteFile.LastModified > 0 && File.Exists(row.LocalPath))
								{
									File.SetLastWriteTimeUtc(row.LocalPath, DateTimeOffset.FromUnixTimeMilliseconds(remoteFile.LastModified).UtcDateTime);
								}
							}
							catch (Exception ex)
							{
								((BaseUnityPlugin)_plugin).Logger.LogWarning((object)("对齐本地存档时间失败(" + row.FileName + "): " + ex.Message));
							}
							row.ApplyRemote(remoteFile);
							row.RefreshLocal();
							ApplyQuota(remoteListing);
						}
						if (flag)
						{
							row.MarkUploaded();
						}
						row.Complete();
						((BaseUnityPlugin)_plugin).Logger.LogInfo((object)$"已上传 {row.FileName}({FormatSize(row.LocalSize)},{Seconds(started):0.0}s)");
						return;
					}
					RemoteFile remoteFile2 = row.Remote ?? new RemoteFile
					{
						FileName = row.FileName,
						FileSize = row.RemoteSize,
						LastModified = row.RemoteMtimeMs
					};
					if (!(await _plugin.DownloadSingleFile(remoteFile2, row.AddProgress, token)))
					{
						if (!token.IsCancellationRequested)
						{
							row.Fail(string.IsNullOrEmpty(_plugin.LastServerError) ? "下载失败,详见 BepInEx 日志" : ("下载失败:" + Trim(_plugin.LastServerError, 52)));
						}
					}
					else
					{
						row.FillProgress();
						row.RefreshLocal();
						row.Complete();
						((BaseUnityPlugin)_plugin).Logger.LogInfo((object)$"已下载 {row.FileName}({FormatSize(row.LocalSize)},{Seconds(started):0.0}s)");
					}
				}
				catch (OperationCanceledException)
				{
					row.Canceled();
				}
				catch (Exception ex3)
				{
					row.Fail(ShortError(ex3));
					((BaseUnityPlugin)_plugin).Logger.LogError((object)("传输失败 " + row.FileName + ": " + _plugin.FormatException(ex3)));
				}
				finally
				{
					if (slotTaken)
					{
						slots.Release();
					}
					row.End();
					RebuildView();
					ScheduleRefresh(0.6f);
				}
			}

			private void CancelRow(SaveRow row)
			{
				if (row == null || !row.IsBusy)
				{
					return;
				}
				try
				{
					row.Cts?.Cancel();
				}
				catch (ObjectDisposedException)
				{
				}
			}

			private void CancelAll()
			{
				for (int i = 0; i < _rows.Count; i++)
				{
					if (_rows[i].IsBusy)
					{
						CancelRow(_rows[i]);
					}
				}
			}

			private double Seconds(DateTime startedUtc)
			{
				return Math.Max(0.0, (DateTime.UtcNow - startedUtc).TotalSeconds);
			}

			internal void Draw()
			{
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_011f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0134: Unknown result type (might be due to invalid IL or missing references)
				//IL_0191: Unknown result type (might be due to invalid IL or missing references)
				//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
				//IL_0248: Unknown result type (might be due to invalid IL or missing references)
				//IL_024e: Unknown result type (might be due to invalid IL or missing references)
				//IL_026e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0287: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
				//IL_009f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0315: Unknown result type (might be due to invalid IL or missing references)
				//IL_031b: Invalid comparison between Unknown and I4
				//IL_0322: Unknown result type (might be due to invalid IL or missing references)
				//IL_0328: Invalid comparison between Unknown and I4
				//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
				if (!_visible)
				{
					if (_depthRaised)
					{
						GUI.depth = 0;
						_depthRaised = false;
					}
					if (GUI.GetNameOfFocusedControl() == "dsprs-search")
					{
						GUI.FocusControl((string)null);
					}
					return;
				}
				GUI.depth = -100;
				_depthRaised = true;
				_scale = ComputeScale();
				EnsureAssets();
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)0;
				if (Event.current != null)
				{
					_lastMouseGui = Event.current.mousePosition;
				}
				UpdateWindowPosition();
				RefreshOpacity();
				_blockInput = _openDropdown != DropdownKind.None;
				if (Event.current != null && (int)Event.current.type == 0 && GUI.GetNameOfFocusedControl() == "dsprs-search")
				{
					Rect val = R(946f, 51f, 198f, 26f);
					if (!((Rect)(ref val)).Contains(Event.current.mousePosition))
					{
						GUI.FocusControl((string)null);
					}
				}
				float num = 0.1f + 0.22f * Mathf.Max(0f, _opacityBase);
				DrawRect(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), new Color(0f, 0f, 0f, num));
				DrawRounded(new Rect(_px - S(3f), _py + S(4f), S(1160f) + S(6f), S(700f) + S(4f)), new Color(0f, 0f, 0f, 0.35f), S(12f), null, 0f);
				DrawRounded(R(0f, 0f, 1160f, 700f), PanelBg, S(10f), Border, S(1f));
				DrawHeader();
				DrawToolbar();
				DrawTableHead();
				DrawList();
				DrawFooter();
				DrawRect(R(10f, 0f, 1140f, 1f), Border);
				DrawRect(R(12f, 1f, 1136f, 1f), C(255, 255, 255, 0.09f));
				DrawRect(R(10f, 699f, 1140f, 1f), Border);
				DrawRect(R(0f, 10f, 1f, 680f), Border);
				DrawRect(R(1159f, 10f, 1f, 680f), Border);
				DrawDropdown();
				if (Event.current != null && (int)Event.current.type != 8 && (int)Event.current.type != 7)
				{
					Event.current.Use();
				}
			}

			private void RefreshOpacity()
			{
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00df: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
				//IL_010f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0114: Unknown result type (might be due to invalid IL or missing references)
				//IL_0131: Unknown result type (might be due to invalid IL or missing references)
				//IL_0136: Unknown result type (might be due to invalid IL or missing references)
				//IL_0153: Unknown result type (might be due to invalid IL or missing references)
				//IL_0158: Unknown result type (might be due to invalid IL or missing references)
				float num = Mathf.Clamp(_plugin.PanelOpacity, 0.35f, 1f);
				if (!(Mathf.Abs(num - _opacityBase) < 0.001f))
				{
					_opacityBase = num;
					PanelBg = C(12, 33, 47, num);
					HeaderBg = C(27, 62, 84, Mathf.Min(1f, num + 0.14f));
					ToolbarBg = C(17, 44, 59, Mathf.Min(1f, num + 0.12f));
					TableHeadBg = C(15, 38, 52, Mathf.Min(1f, num + 0.12f));
					FooterBg = C(15, 38, 52, Mathf.Min(1f, num + 0.12f));
					RowBgA = C(22, 49, 64, num * 0.4f);
					RowBgB = C(18, 42, 56, num * 0.22f);
					RowHover = C(34, 72, 93, num * 0.62f);
					Separator = C(35, 68, 87, Mathf.Min(1f, num * 0.6f));
					Border = C(48, 84, 105, Mathf.Min(1f, num * 1.1f));
				}
			}

			private void UpdateWindowPosition()
			{
				float num = 1160f * _scale;
				float num2 = 700f * _scale;
				float num3 = 72f * _scale;
				float num4 = 0f - (num - num3);
				float num5 = (float)Screen.width - num3;
				float num6 = 0f;
				float num7 = Mathf.Max(0f, (float)Screen.height - num3);
				float num8 = ((float)Screen.width - num) * 0.5f + _offsetX * _scale;
				float num9 = ((float)Screen.height - num2) * 0.5f + _offsetY * _scale;
				_px = ((num5 > num4) ? Mathf.Clamp(num8, num4, num5) : num4);
				_py = ((num7 > num6) ? Mathf.Clamp(num9, num6, num7) : num6);
			}

			private void HandleWindowDrag(Rect rect)
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Invalid comparison between Unknown and I4
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d9: Invalid comparison between Unknown and I4
				//IL_0074: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e3: Invalid comparison between Unknown and I4
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				Event current = Event.current;
				if (current != null)
				{
					if (!_dragging && (int)current.type == 0 && current.button == 0 && ((Rect)(ref rect)).Contains(current.mousePosition))
					{
						_dragging = true;
						_dragStartMouse = current.mousePosition;
						_dragStartOffset = new Vector2(_offsetX, _offsetY);
						current.Use();
					}
					else if (_dragging && (int)current.type == 3)
					{
						Vector2 val = current.mousePosition - _dragStartMouse;
						_offsetX = _dragStartOffset.x + val.x / _scale;
						_offsetY = _dragStartOffset.y + val.y / _scale;
						current.Use();
					}
					else if (_dragging && ((int)current.type == 1 || (int)current.type == 11))
					{
						_dragging = false;
						current.Use();
					}
				}
			}

			private float ComputeScale()
			{
				float num = (float)Screen.height / 1080f;
				float num2 = (float)Screen.width * 0.96f / 1160f;
				float num3 = (float)Screen.height * 0.94f / 700f;
				return Mathf.Clamp(Mathf.Min(num, Mathf.Min(num2, num3)), 0.62f, 2.6f);
			}

			private Font EnsureFont()
			{
				if ((Object)(object)_font != (Object)null)
				{
					return _font;
				}
				try
				{
					_font = Font.CreateDynamicFontFromOSFont(new string[5] { "Microsoft YaHei UI", "Microsoft YaHei", "SimHei", "Noto Sans CJK SC", "Arial" }, 18);
				}
				catch
				{
				}
				if ((Object)(object)_font == (Object)null)
				{
					_font = GUI.skin.font;
				}
				return _font;
			}

			private void EnsureAssets()
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Expected O, but got Unknown
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_010b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0123: Unknown result type (might be due to invalid IL or missing references)
				//IL_013b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0153: Unknown result type (might be due to invalid IL or missing references)
				//IL_016b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0183: Unknown result type (might be due to invalid IL or missing references)
				//IL_019b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
				//IL_0213: Unknown result type (might be due to invalid IL or missing references)
				//IL_022b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0243: Unknown result type (might be due to invalid IL or missing references)
				//IL_025b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0273: Unknown result type (might be due to invalid IL or missing references)
				//IL_028b: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c2: Expected O, but got Unknown
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
				EnsureFont();
				if ((Object)(object)_white == (Object)null)
				{
					_white = new Texture2D(1, 1, (TextureFormat)4, false);
					_white.SetPixel(0, 0, Color.white);
					_white.Apply();
					((Object)_white).hideFlags = (HideFlags)61;
				}
				if ((Object)(object)_logo == (Object)null)
				{
					_logo = MakeLogoTexture();
				}
				if ((Object)(object)_magnifier == (Object)null)
				{
					_magnifier = MakeMagnifierTexture();
				}
				try
				{
					GUI.skin.settings.cursorColor = AccentCyan;
					GUI.skin.settings.selectionColor = new Color(0.24f, 0.55f, 0.68f, 0.55f);
				}
				catch
				{
				}
				if (!(Mathf.Abs(_builtScale - _scale) < 0.001f))
				{
					_builtScale = _scale;
					_styleTitle = MakeStyle(16f, (FontStyle)1, (TextAnchor)3, TextPrimary);
					_styleSubtitle = MakeStyle(11.5f, (FontStyle)0, (TextAnchor)3, TextSecondary);
					_styleRowName = MakeStyle(13.5f, (FontStyle)0, (TextAnchor)3, TextPrimary);
					_styleMetaRight = MakeStyle(11.5f, (FontStyle)0, (TextAnchor)5, TextSecondary);
					_styleRight = MakeStyle(12.5f, (FontStyle)0, (TextAnchor)5, TextPrimary);
					_styleSmallRight = MakeStyle(11.5f, (FontStyle)0, (TextAnchor)5, TextSecondary);
					_styleSmallPrimary = MakeStyle(11.5f, (FontStyle)0, (TextAnchor)3, TextPrimary);
					_styleDimSmall = MakeStyle(11.5f, (FontStyle)0, (TextAnchor)3, TextDim);
					_styleTableHead = MakeStyle(10.5f, (FontStyle)0, (TextAnchor)3, TextDim);
					_styleTableHeadRight = MakeStyle(10.5f, (FontStyle)0, (TextAnchor)5, TextDim);
					_styleTableHeadCenter = MakeStyle(10.5f, (FontStyle)0, (TextAnchor)4, TextDim);
					_styleStatus = MakeStyle(11.5f, (FontStyle)0, (TextAnchor)3, Color.white);
					_styleLegend = MakeStyle(11.5f, (FontStyle)0, (TextAnchor)3, Color.white);
					_styleButton = MakeStyle(11.5f, (FontStyle)0, (TextAnchor)4, Color.white);
					_styleProgress = MakeStyle(10.5f, (FontStyle)0, (TextAnchor)3, Color.white);
					_styleClose = MakeStyle(18f, (FontStyle)0, (TextAnchor)4, Color.white);
					_stylePlaceholder = MakeStyle(11.5f, (FontStyle)0, (TextAnchor)3, TextDim);
					_styleEmptyTitle = MakeStyle(15f, (FontStyle)0, (TextAnchor)4, TextPrimary);
					_styleEmptySub = MakeStyle(11.5f, (FontStyle)0, (TextAnchor)4, TextDim);
					_styleBlank = new GUIStyle(GUIStyle.none);
					BuildSearchStyle();
				}
			}

			private GUIStyle MakeStyle(float size, FontStyle fontStyle, TextAnchor anchor, Color color)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Expected O, but got Unknown
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0076: Expected O, but got Unknown
				//IL_0076: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_0089: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: Expected O, but got Unknown
				GUIStyle val = new GUIStyle(GUI.skin.label)
				{
					font = _font,
					fontSize = Mathf.Max(9, Mathf.RoundToInt(size * _scale)),
					fontStyle = fontStyle,
					alignment = anchor,
					clipping = (TextClipping)1,
					wordWrap = false,
					richText = false,
					padding = new RectOffset(0, 0, 0, 0),
					margin = new RectOffset(0, 0, 0, 0)
				};
				val.normal.textColor = color;
				val.hover.textColor = color;
				val.active.textColor = color;
				val.focused.textColor = color;
				return val;
			}

			private void BuildSearchStyle()
			{
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_0080: Unknown result type (might be due to invalid IL or missing references)
				//IL_0085: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: Unknown result type (might be due to invalid IL or missing references)
				//IL_00af: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cc: Expected O, but got Unknown
				//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fb: Expected O, but got Unknown
				//IL_0100: Expected O, but got Unknown
				//IL_0163: Unknown result type (might be due to invalid IL or missing references)
				//IL_0178: Unknown result type (might be due to invalid IL or missing references)
				//IL_018d: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
				int num = Mathf.Max(3, Mathf.RoundToInt(6f * _scale));
				if ((Object)(object)_searchBgTex != (Object)null)
				{
					Object.Destroy((Object)(object)_searchBgTex);
					_searchBgTex = null;
				}
				_searchBgTex = MakeRoundedBoxTexture(num, C(8, 24, 35, 1f), C(41, 78, 99, 1f), Mathf.Max(1, Mathf.RoundToInt(_scale)));
				_styleSearch = new GUIStyle(GUI.skin.textField)
				{
					font = _font,
					fontSize = Mathf.Max(9, Mathf.RoundToInt(12f * _scale)),
					alignment = (TextAnchor)3,
					clipping = (TextClipping)1,
					border = new RectOffset(num, num, num, num),
					padding = new RectOffset(Mathf.RoundToInt(26f * _scale), Mathf.RoundToInt(8f * _scale), 0, 0)
				};
				_styleSearch.normal.background = _searchBgTex;
				_styleSearch.hover.background = _searchBgTex;
				_styleSearch.active.background = _searchBgTex;
				_styleSearch.focused.background = _searchBgTex;
				_styleSearch.normal.textColor = TextPrimary;
				_styleSearch.hover.textColor = TextPrimary;
				_styleSearch.active.textColor = TextPrimary;
				_styleSearch.focused.textColor = TextPrimary;
			}

			private void DrawHeader()
			{
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
				//IL_0114: Unknown result type (might be due to invalid IL or missing references)
				//IL_0147: Unknown result type (might be due to invalid IL or missing references)
				//IL_0166: Unknown result type (might be due to invalid IL or missing references)
				//IL_018b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b5: Expected O, but got Unknown
				//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
				//IL_01df: Unknown result type (might be due to invalid IL or missing references)
				//IL_0202: Unknown result type (might be due to invalid IL or missing references)
				//IL_020c: Expected O, but got Unknown
				//IL_0207: Unknown result type (might be due to invalid IL or missing references)
				//IL_023b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0241: Unknown result type (might be due to invalid IL or missing references)
				//IL_024b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0260: Unknown result type (might be due to invalid IL or missing references)
				//IL_0259: Unknown result type (might be due to invalid IL or missing references)
				//IL_027e: Unknown result type (might be due to invalid IL or missing references)
				//IL_028f: Unknown result type (might be due to invalid IL or missing references)
				//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_02af: Unknown result type (might be due to invalid IL or missing references)
				//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_031b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0325: Unknown result type (might be due to invalid IL or missing references)
				//IL_033d: Unknown result type (might be due to invalid IL or missing references)
				//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
				Rect rect = default(Rect);
				((Rect)(ref rect))..ctor(_px + S(1f), _py + S(1f), S(1160f) - S(2f), S(44f));
				DrawRounded(rect, HeaderBg, S(9f), null, 0f);
				DrawRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + S(34f), ((Rect)(ref rect)).width, S(10f)), HeaderBg);
				DrawRect(new Rect(((Rect)(ref rect)).x + S(1f), ((Rect)(ref rect)).y + ((Rect)(ref rect)).height - S(1f), ((Rect)(ref rect)).width - S(2f), S(1f)), C(120, 170, 195, 0.22f));
				HandleWindowDrag(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width - S(36f), ((Rect)(ref rect)).height));
				GUI.DrawTexture(R(18f, 11f, 22f, 22f), (Texture)(object)_logo);
				GUI.Label(R(48f, 0f, 240f, 44f), "DSP Remote Saves", _styleTitle);
				float num = _styleTitle.CalcSize(new GUIContent("DSP Remote Saves")).x / _scale;
				GUI.Label(R(48f + num + 12f, 0f, 140f, 44f), "云存档同步", _styleSubtitle);
				string statusLine = StatusLine;
				float num2 = _styleStatus.CalcSize(new GUIContent(statusLine)).x / _scale;
				float num3 = 1110f - num2;
				DrawCircle(R(num3 - 11f, 19.5f, 5f, 5f), StatusColor);
				Color color = GUI.color;
				GUI.color = ((_connection == ConnState.Failed) ? AccentRed : TextSecondary);
				GUI.Label(R(num3, 0f, num2 + 2f, 44f), statusLine, _styleStatus);
				GUI.color = color;
				Rect val = R(1122f, 9f, 26f, 26f);
				if (((Rect)(ref val)).Contains(Event.current.mousePosition) && !_blockInput)
				{
					DrawRounded(val, C(255, 255, 255, 0.08f), S(5f), null, 0f);
				}
				GUI.color = C(190, 210, 222, 1f);
				GUI.Label(val, "×", _styleClose);
				GUI.color = color;
				if (Click(val))
				{
					Close();
				}
			}

			private void DrawToolbar()
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00da: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_011f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0125: Unknown result type (might be due to invalid IL or missing references)
				//IL_0144: Unknown result type (might be due to invalid IL or missing references)
				//IL_016e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0184: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0201: Unknown result type (might be due to invalid IL or missing references)
				//IL_0209: Unknown result type (might be due to invalid IL or missing references)
				//IL_0265: Unknown result type (might be due to invalid IL or missing references)
				//IL_025e: Unknown result type (might be due to invalid IL or missing references)
				//IL_021e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0233: Unknown result type (might be due to invalid IL or missing references)
				//IL_026f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0295: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_033d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0372: Unknown result type (might be due to invalid IL or missing references)
				DrawRect(R(0f, 44f, 1160f, 40f), ToolbarBg);
				DrawRect(R(0f, 83f, 1160f, 1f), Separator);
				GUI.Label(R(18f, 44f, 30f, 40f), "排序", _styleDimSmall);
				GUI.Label(R(50f, 44f, 70f, 40f), SortLabel, _styleSmallPrimary);
				Color color = GUI.color;
				GUI.color = TextDim;
				GUI.Label(R(112f, 44f, 14f, 40f), "▾", _styleLegend);
				GUI.color = color;
				if (Click(R(46f, 50f, 82f, 28f)))
				{
					ToggleDropdown(DropdownKind.Sort);
				}
				DrawRect(R(140f, 54f, 1f, 20f), Separator);
				GUI.Label(R(156f, 44f, 60f, 40f), "传输方向", _styleDimSmall);
				GUI.Label(R(214f, 44f, 48f, 40f), FilterLabel, _styleSmallPrimary);
				GUI.color = TextDim;
				GUI.Label(R(260f, 44f, 14f, 40f), "▾", _styleLegend);
				GUI.color = color;
				if (Click(R(210f, 50f, 66f, 28f)))
				{
					ToggleDropdown(DropdownKind.Filter);
				}
				Rect val = R(662f, 51f, 52f, 26f);
				if (((Rect)(ref val)).Contains(Event.current.mousePosition) && !_blockInput)
				{
					DrawRounded(val, C(255, 255, 255, 0.06f), S(4f), null, 0f);
				}
				GUI.color = (_refreshing ? TextFaint : TextSecondary);
				GUI.Label(val, _refreshing ? "刷新中" : "刷新", _styleButton);
				GUI.color = color;
				if (Click(val) && !_refreshing)
				{
					Refresh();
				}
				DrawQuotaMeter();
				Rect val2 = R(946f, 51f, 198f, 26f);
				bool flag = GUI.GetNameOfFocusedControl() == "dsprs-search";
				GUI.SetNextControlName("dsprs-search");
				string text = GUI.TextField(val2, _search ?? string.Empty, 80, _styleSearch);
				if (text != _search)
				{
					_search = text;
					_scroll = 0f;
					RebuildView();
				}
				GUI.DrawTexture(R(952f, 58f, 13f, 13f), (Texture)(object)_magnifier);
				if (string.IsNullOrEmpty(_search) && !flag)
				{
					GUI.Label(R(972f, 44f, 160f, 40f), "搜索存档名称", _stylePlaceholder);
				}
			}

			private void DrawQuotaMeter()
			{
				//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
				//IL_011f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0124: Unknown result type (might be due to invalid IL or missing references)
				//IL_0160: Unknown result type (might be due to invalid IL or missing references)
				//IL_0165: Unknown result type (might be due to invalid IL or missing references)
				//IL_0118: Unknown result type (might be due to invalid IL or missing references)
				//IL_0111: Unknown result type (might be due to invalid IL or missing references)
				long num = Math.Max(0L, _usedBytes) + Math.Max(0L, _reservedBytes);
				int num2;
				float num3;
				if (_hasQuota)
				{
					num2 = ((_quotaBytes > 0) ? 1 : 0);
					if (num2 != 0)
					{
						num3 = Mathf.Clamp01((float)((double)num / (double)_quotaBytes));
						goto IL_004b;
					}
				}
				else
				{
					num2 = 0;
				}
				num3 = 0f;
				goto IL_004b;
				IL_004b:
				float num4 = num3;
				string text = ((num2 != 0) ? ("云空间 " + FormatSize(num) + " / " + FormatSize(_quotaBytes)) : ((num <= 0) ? "云空间 —" : ("云空间 已用 " + FormatSize(num))));
				GUI.Label(R(720f, 50f, 212f, 14f), text, _styleSmallRight);
				Rect rect = R(720f, 68f, 212f, 5f);
				DrawRounded(rect, ProgressTrack, S(2.5f), null, 0f);
				if (num4 > 0f)
				{
					Color color = ((num4 >= 0.9f) ? AccentRed : ((num4 >= 0.75f) ? AccentAmber : ProgressUp));
					float num5 = Mathf.Clamp(((Rect)(ref rect)).width * num4, S(2f), ((Rect)(ref rect)).width);
					DrawRounded(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num5, ((Rect)(ref rect)).height), color, S(2.5f), null, 0f);
				}
			}

			private void DrawTableHead()
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0085: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_00de: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
				float num = 84f;
				DrawRect(R(0f, num, 1160f, 26f), TableHeadBg);
				GUI.Label(R(18f, num, 200f, 26f), "名称", _styleTableHead);
				GUI.Label(R(460f, num, 240f, 26f), "本地版本", _styleTableHeadRight);
				GUI.Label(R(720f, num, 240f, 26f), "同步方向", _styleTableHeadCenter);
				GUI.Label(R(900f, num, 244f, 26f), "云端版本", _styleTableHeadRight);
				DrawRect(R(0f, num + 26f - 1f, 1160f, 1f), Separator);
			}

			private void DrawList()
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0094: Unknown result type (might be due to invalid IL or missing references)
				//IL_0099: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Unknown result type (might be due to invalid IL or missing references)
				//IL_010d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0121: Unknown result type (might be due to invalid IL or missing references)
				//IL_0141: Unknown result type (might be due to invalid IL or missing references)
				//IL_0146: Unknown result type (might be due to invalid IL or missing references)
				//IL_0152: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00af: Invalid comparison between Unknown and I4
				//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
				//IL_024b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01db: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
				Rect val = R(0f, 110f, 1160f, 546f);
				float num = 0f;
				for (int i = 0; i < _view.Count; i++)
				{
					num += S(58f);
					if (_view[i].IsBusy)
					{
						num += S(30f);
					}
					if (_view[i].Status == RowStatus.Failed)
					{
						num += S(24f);
					}
				}
				_contentHeight = num;
				Vector2 mousePosition = Event.current.mousePosition;
				if (((Rect)(ref val)).Contains(mousePosition) && (int)Event.current.type == 6)
				{
					_scroll += Event.current.delta.y * S(48f);
					Event.current.Use();
				}
				_scroll = Mathf.Clamp(_scroll, 0f, Mathf.Max(0f, num - ((Rect)(ref val)).height));
				_groupMouse = new Vector2((mousePosition.x - _px) / _scale, (mousePosition.y - _py - S(110f)) / _scale);
				_inGroup = true;
				GUI.BeginGroup(val);
				if (_view.Count == 0)
				{
					DrawEmptyState();
				}
				else
				{
					float num2 = (0f - _scroll) / _scale;
					for (int j = 0; j < _view.Count; j++)
					{
						SaveRow saveRow = _view[j];
						bool isBusy = saveRow.IsBusy;
						bool flag = saveRow.Status == RowStatus.Failed;
						if (num2 + 58f >= 0f && num2 <= 546f)
						{
							int num3;
							if (!_blockInput)
							{
								Rect val2 = new Rect(0f, num2, 1160f, 58f);
								num3 = (((Rect)(ref val2)).Contains(_groupMouse) ? 1 : 0);
							}
							else
							{
								num3 = 0;
							}
							bool hover = (byte)num3 != 0;
							DrawRow(saveRow, j, num2, hover);
						}
						num2 += 58f;
						if (isBusy)
						{
							num2 += 30f;
						}
						if (flag)
						{
							num2 += 24f;
						}
					}
				}
				GUI.EndGroup();
				_inGroup = false;
				DrawScrollbar(val, num);
			}

			private bool MouseOverPanel()
			{
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				if (_scale <= 0f)
				{
					return false;
				}
				Rect val = new Rect(_px, _py, 1160f * _scale, 700f * _scale);
				return ((Rect)(ref val)).Contains(_lastMouseGui);
			}

			private Vector2 LocalMouse(Rect view)
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				Vector2 mousePosition = Event.current.mousePosition;
				return new Vector2(mousePosition.x - ((Rect)(ref view)).x, mousePosition.y - ((Rect)(ref view)).y);
			}

			private void DrawEmptyState()
			{
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00da: Unknown result type (might be due to invalid IL or missing references)
				bool flag = false;
				string text;
				string text2;
				if (_loading)
				{
					text = "正在获取云端存档…";
					text2 = "连接 " + ServerDisplay;
				}
				else if (!string.IsNullOrEmpty(_listError))
				{
					text = "连接失败";
					text2 = _listError;
					flag = true;
				}
				else if (_rows.Count == 0)
				{
					text = "还没有可同步的存档";
					text2 = "本地存档会自动出现在这里,点击上传即可备份到云端";
				}
				else
				{
					text = "没有匹配的存档";
					text2 = "试试其它关键字,或把筛选切回“全部”";
				}
				GUI.Label(L(0f, 229f, 1160f, 26f), text, _styleEmptyTitle);
				GUI.Label(L(0f, 261f, 1160f, 22f), Trim(text2, 56), _styleEmptySub);
				if (flag)
				{
					Rect rect = L(530f, 295f, 100f, 28f);
					if (DrawSecondaryButton(rect, "重试"))
					{
						Refresh();
					}
				}
			}

			private void DrawScrollbar(Rect view, float contentHeight)
			{
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_0104: Unknown result type (might be due to invalid IL or missing references)
				//IL_011a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0143: Unknown result type (might be due to invalid IL or missing references)
				//IL_0148: Unknown result type (might be due to invalid IL or missing references)
				//IL_014f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0158: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ee: Invalid comparison between Unknown and I4
				//IL_0195: Unknown result type (might be due to invalid IL or missing references)
				//IL_019b: Invalid comparison between Unknown and I4
				//IL_0169: Unknown result type (might be due to invalid IL or missing references)
				//IL_019d: Unknown result type (might be due to invalid IL or missing references)
				if (!(contentHeight <= ((Rect)(ref view)).height + 1f))
				{
					Rect rect = default(Rect);
					((Rect)(ref rect))..ctor(((Rect)(ref view)).xMax - S(6f), ((Rect)(ref view)).y + S(4f), S(3f), ((Rect)(ref view)).height - S(8f));
					DrawRounded(rect, C(255, 255, 255, 0.06f), S(2f), null, 0f);
					float num = Mathf.Max(S(26f), ((Rect)(ref rect)).height * (((Rect)(ref view)).height / contentHeight));
					float num2 = Mathf.Max(1f, contentHeight - ((Rect)(ref view)).height);
					float num3 = Mathf.Clamp01(_scroll / num2);
					Rect rect2 = default(Rect);
					((Rect)(ref rect2))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + (((Rect)(ref rect)).height - num) * num3, ((Rect)(ref rect)).width, num);
					DrawRounded(rect2, C(190, 220, 235, 0.32f), S(2f), null, 0f);
					Vector2 mousePosition = Event.current.mousePosition;
					if ((int)Event.current.type == 0 && ((Rect)(ref rect2)).Contains(mousePosition))
					{
						_scrollDragging = true;
						_scrollDragOffset = mousePosition.y - ((Rect)(ref rect2)).y;
						Event.current.Use();
					}
					else if (_scrollDragging && (int)Event.current.type == 3)
					{
						float num4 = Mathf.Clamp01((mousePosition.y - _scrollDragOffset - ((Rect)(ref rect)).y) / Mathf.Max(1f, ((Rect)(ref rect)).height - num));
						_scroll = num4 * num2;
						Event.current.Use();
					}
					else if ((int)Event.current.type == 1)
					{
						_scrollDragging = false;
					}
				}
			}

			private void DrawRow(SaveRow row, int index, float y, bool hover)
			{
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0094: Unknown result type (might be due to invalid IL or missing references)
				//IL_0099: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00df: Unknown result type (might be due to invalid IL or missing references)
				//IL_0100: Unknown result type (might be due to invalid IL or missing references)
				//IL_0103: Unknown result type (might be due to invalid IL or missing references)
				//IL_0105: Unknown result type (might be due to invalid IL or missing references)
				//IL_012a: Unknown result type (might be due to invalid IL or missing references)
				//IL_012f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0146: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_0186: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_0239: Unknown result type (might be due to invalid IL or missing references)
				//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
				//IL_0369: Unknown result type (might be due to invalid IL or missing references)
				//IL_039a: Unknown result type (might be due to invalid IL or missing references)
				//IL_040f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0415: Unknown result type (might be due to invalid IL or missing references)
				//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
				//IL_0314: Unknown result type (might be due to invalid IL or missing references)
				//IL_0331: Unknown result type (might be due to invalid IL or missing references)
				//IL_02da: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
				bool isBusy = row.IsBusy;
				bool flag = row.Status == RowStatus.Failed;
				S(58f);
				Color color = ((index % 2 == 0) ? RowBgA : RowBgB);
				if (hover)
				{
					color = RowHover;
				}
				DrawRect(L(0f, y, 1160f, 58f), color);
				Rect rect = L(19f, y + 29f - 4f, 8f, 8f);
				Color color2 = ((!isBusy) ? (flag ? AccentRed : ((row.Direction == RowDirection.Synced) ? C(86, 132, 152, 1f) : C(118, 158, 178, 1f))) : ((row.Kind == TransferKind.Upload) ? AccentCyan : AccentAmber));
				DrawCircle(rect, color2);
				DrawCircle(L(21f, y + 29f - 2f, 4f, 4f), color);
				GUI.Label(L(34f, y, 430f, 58f), Trim(row.DisplayName, 30), _styleRowName);
				if (row.LocalExists)
				{
					GUI.Label(L(462f, y, 138f, 58f), FormatSize(row.LocalSize), _styleRight);
					GUI.Label(L(606f, y, 96f, 58f), FormatTime(row.LocalMtimeUtc.ToLocalTime()), _styleMetaRight);
				}
				else
				{
					DrawDashedPlaceholder(L(462f, y + 15f, 240f, 28f), "无本地存档");
				}
				float y2 = y + 15f;
				float h = 28f;
				if (row.Direction == RowDirection.Synced && !isBusy && !flag)
				{
					DrawSyncChip(L(790f, y2, 92f, h));
				}
				else
				{
					TransferKind transferKind = ((row.Direction != RowDirection.Download) ? TransferKind.Upload : TransferKind.Download);
					if (isBusy)
					{
						transferKind = row.Kind;
					}
					bool enabled = row.LocalExists && !isBusy && !_blockInput;
					bool enabled2 = row.RemoteExists && !isBusy && !_blockInput;
					Rect rect2 = L(736f, y2, 76f, h);
					Rect rect3 = L(820f, y2, 76f, h);
					if (transferKind == TransferKind.Download)
					{
						DrawActionLink(rect2, "上传 →", enabled, delegate
						{
							StartTransfer(row, TransferKind.Upload);
						});
						DrawActionButton(rect3, "← 下载", download: true, enabled2, delegate
						{
							StartTransfer(row, TransferKind.Download);
						});
					}
					else
					{
						DrawActionButton(rect2, "上传 →", download: false, enabled, delegate
						{
							StartTransfer(row, TransferKind.Upload);
						});
						DrawActionLink(rect3, "← 下载", enabled2, delegate
						{
							StartTransfer(row, TransferKind.Download);
						});
					}
				}
				if (row.RemoteExists)
				{
					GUI.Label(L(950f, y, 92f, 58f), FormatSize(row.RemoteSize), _styleRight);
					GUI.Label(L(1050f, y, 94f, 58f), FormatTime(FromUnixMs(row.RemoteMtimeMs).ToLocalTime()), _styleMetaRight);
				}
				else
				{
					DrawDashedPlaceholder(L(938f, y + 15f, 206f, 28f), "无云端存档");
				}
				DrawRect(L(16f, y + 58f - 1f, 1128f, 1f), Separator);
				if (isBusy)
				{
					DrawProgressLine(row, y + 58f);
				}
				else if (flag)
				{
					DrawErrorLine(row, y + 58f);
				}
			}

			private void DrawProgressLine(SaveRow row, float y)
			{
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c8: Unknown result type (might be due to invalid IL or missing references)