using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.NET.Common;
using BepInExResoniteShim;
using BepisResoniteWrapper;
using FrooxEngine;
using FrooxEngine.UIX;
using HarmonyLib;
using SkyFrost.Base;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(/*Could not decode attribute arguments.*/)]
[assembly: TargetFramework(".NETCoreApp,Version=v10.0", FrameworkDisplayName = ".NET 10.0")]
[assembly: AssemblyCompany("markn2000")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.12.0")]
[assembly: AssemblyInformationalVersion("0.3.12+b15942700584b31618d9bc7e21dff605fa824bbc")]
[assembly: AssemblyProduct("SmoothContacts")]
[assembly: AssemblyTitle("SmoothContacts")]
[assembly: InternalsVisibleTo("SmoothContacts.Checks")]
[assembly: AssemblyVersion("0.3.12.0")]
[module: RefSafetyRules(11)]
namespace SmoothContacts;
[ResonitePlugin("markn2000.SmoothContacts", "SmoothContacts", "0.3.12", "markn2000", "https://github.com/MarkN2000/SmoothContacts")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class Plugin : BasePlugin
{
public override void Load()
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Expected O, but got Unknown
((BasePlugin)this).Config.SaveOnConfigSet = false;
ResoniteHooks.OnEngineReady += new Action(OnEngineReady);
}
private void OnEngineReady()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Expected O, but got Unknown
ResoniteHooks.OnEngineReady -= new Action(OnEngineReady);
try
{
ContactsPatches.BindSettings(((BasePlugin)this).Config);
if (!File.Exists(((BasePlugin)this).Config.ConfigFilePath))
{
((BasePlugin)this).Config.Save();
}
ContactsPatches.ReportError = [CompilerGenerated] (global::System.Exception error) =>
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
ManualLogSource log2 = ((BasePlugin)this).Log;
bool flag2 = default(bool);
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(33, 1, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Error while processing Contacts: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<global::System.Exception>(error);
}
log2.LogError(val2);
};
ContactsPatches.Apply(((BasePlugin)this).HarmonyInstance);
((BasePlugin)this).Log.LogInfo((object)"SmoothContacts: Contact loading and search restoration are batched while Contacts is active.");
}
catch (global::System.Exception ex)
{
((BasePlugin)this).HarmonyInstance.UnpatchSelf();
ManualLogSource log = ((BasePlugin)this).Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(63, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to apply SmoothContacts. Its patches have been removed: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<global::System.Exception>(ex);
}
log.LogError(val);
}
}
public override bool Unload()
{
return false;
}
}
internal static class ContactsPatches
{
internal sealed class Loading(ContactManager manager, Action<ContactData> update)
{
internal readonly ContactManager Manager = manager;
internal readonly Action<ContactData> Update = update;
internal List<ContactData>? Contacts;
internal Dictionary<string, int> Order = new Dictionary<string, int>();
internal readonly Dictionary<string, ContactData> Deferred = new Dictionary<string, ContactData>();
internal int Position;
internal bool Creating;
internal string? Selection;
internal Slot? Spacer;
internal int ReservedRows = -1;
private long extraRows;
internal long RowOrder(string id)
{
int num = default(int);
return (Order.TryGetValue(id, ref num) ? num : (Contacts.Count + extraRows++)) * 100;
}
internal ValueTuple<int, int> TakeBatch(int remaining)
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
int position = Position;
Position += Math.Min(remaining, Contacts.Count - Position);
return new ValueTuple<int, int>(position, Position);
}
internal void ClearSpacer()
{
ReservedRows = 0;
Slot spacer = Spacer;
Spacer = null;
if (spacer != null && !((Worker)spacer).IsRemoved)
{
spacer.Destroy();
}
}
}
[CompilerGenerated]
private sealed class <>c__DisplayClass18_0
{
[StructLayout((LayoutKind)3)]
private struct <<Start>b__0>d : IAsyncStateMachine
{
public int <>1__state;
public AsyncTaskMethodBuilder <>t__builder;
public <>c__DisplayClass18_0 <>4__this;
private global::System.Exception <failure>5__2;
private ValueTuple<List<ContactData>, Dictionary<string, int>> <prepared>5__3;
private ToBackground <>u__1;
private ToWorld <>u__2;
private void MoveNext()
{
//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: 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_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_0115: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_0225: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: 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_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: 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_003b: 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_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: 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_00da: 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_01ae: 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_01b5: Unknown result type (might be due to invalid IL or missing references)
//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
int num = <>1__state;
<>c__DisplayClass18_0 CS$<>8__locals9 = <>4__this;
try
{
ToWorld val;
if (num != 0)
{
if (num == 1)
{
val = <>u__2;
<>u__2 = default(ToWorld);
num = (<>1__state = -1);
goto IL_014c;
}
<failure>5__2 = null;
<prepared>5__3 = new ValueTuple<List<ContactData>, Dictionary<string, int>>(new List<ContactData>(), new Dictionary<string, int>());
}
try
{
ToBackground val3;
if (num != 0)
{
ToBackground val2 = default(ToBackground);
val3 = ((ToBackground)(ref val2)).GetAwaiter();
if (!((ToBackground)(ref val3)).IsCompleted)
{
num = (<>1__state = 0);
<>u__1 = val3;
((AsyncTaskMethodBuilder)(ref <>t__builder)).AwaitOnCompleted<ToBackground, <<Start>b__0>d>(ref val3, ref this);
return;
}
}
else
{
val3 = <>u__1;
<>u__1 = default(ToBackground);
num = (<>1__state = -1);
}
((ToBackground)(ref val3)).GetResult();
List<ContactData> val4 = new List<ContactData>();
CS$<>8__locals9.manager.ForeachContactData((Action<ContactData>)val4.Add);
<prepared>5__3 = Prepare(val4, delegate(ContactData data)
{
UserMessages userMessages = CS$<>8__locals9.messages.GetUserMessages(data.UserId);
return (userMessages != null) ? userMessages.UnreadCount : 0;
});
}
catch (global::System.Exception ex)
{
<failure>5__2 = ex;
}
ToWorld val5 = default(ToWorld);
val = ((ToWorld)(ref val5)).GetAwaiter();
if (!((ToWorld)(ref val)).IsCompleted)
{
num = (<>1__state = 1);
<>u__2 = val;
((AsyncTaskMethodBuilder)(ref <>t__builder)).AwaitOnCompleted<ToWorld, <<Start>b__0>d>(ref val, ref this);
return;
}
goto IL_014c;
IL_014c:
((ToWorld)(ref val)).GetResult();
Loading loading = default(Loading);
if (!((Worker)CS$<>8__locals9.dialog).IsDisposed && !((ComponentBase<Component>)(object)CS$<>8__locals9.dialog).IsDestroyed && Pending.TryGetValue(CS$<>8__locals9.dialog, ref loading) && loading == CS$<>8__locals9.state)
{
try
{
if (<failure>5__2 != null)
{
throw <failure>5__2;
}
Loading loading2 = CS$<>8__locals9.state;
Loading loading3 = CS$<>8__locals9.state;
ValueTuple<List<ContactData>, Dictionary<string, int>> val6 = <prepared>5__3;
loading2.Contacts = val6.Item1;
loading3.Order = val6.Item2;
}
catch (global::System.Exception error)
{
Abort(CS$<>8__locals9.dialog, error);
}
}
}
catch (global::System.Exception exception)
{
<>1__state = -2;
<failure>5__2 = null;
<prepared>5__3 = default(ValueTuple<List<ContactData>, Dictionary<string, int>>);
((AsyncTaskMethodBuilder)(ref <>t__builder)).SetException(exception);
return;
}
<>1__state = -2;
<failure>5__2 = null;
<prepared>5__3 = default(ValueTuple<List<ContactData>, Dictionary<string, int>>);
((AsyncTaskMethodBuilder)(ref <>t__builder)).SetResult();
}
[DebuggerHidden]
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
((AsyncTaskMethodBuilder)(ref <>t__builder)).SetStateMachine(stateMachine);
}
}
public ContactManager manager;
public MessageManager messages;
public ContactsDialog dialog;
public Loading state;
public Func<ContactData, int> <>9__1;
[AsyncStateMachine(typeof(<<Start>b__0>d))]
internal global::System.Threading.Tasks.Task <Start>b__0()
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
<<Start>b__0>d <<Start>b__0>d = default(<<Start>b__0>d);
<<Start>b__0>d.<>t__builder = AsyncTaskMethodBuilder.Create();
<<Start>b__0>d.<>4__this = this;
<<Start>b__0>d.<>1__state = -1;
((AsyncTaskMethodBuilder)(ref <<Start>b__0>d.<>t__builder)).Start<<<Start>b__0>d>(ref <<Start>b__0>d);
return ((AsyncTaskMethodBuilder)(ref <<Start>b__0>d.<>t__builder)).Task;
}
internal int <Start>b__1(ContactData data)
{
UserMessages userMessages = messages.GetUserMessages(data.UserId);
if (userMessages == null)
{
return 0;
}
return userMessages.UnreadCount;
}
}
internal static ConfigEntry<int> BatchSize = null;
internal static ConfigEntry<int> PauseUpdates = null;
internal static Action<global::System.Exception>? ReportError;
internal static readonly ConditionalWeakTable<ContactsDialog, Loading> Pending = new ConditionalWeakTable<ContactsDialog, Loading>();
internal static readonly ConditionalWeakTable<ContactsDialog, PriorityQueue<ContactItem, long>> Restoring = new ConditionalWeakTable<ContactsDialog, PriorityQueue<ContactItem, long>>();
private static readonly ConditionalWeakTable<ContactsDialog, StrongBox<int>> Pauses = new ConditionalWeakTable<ContactsDialog, StrongBox<int>>();
internal static readonly FieldRef<ContactsDialog, Dictionary<string, ContactItem>> Items = AccessTools.FieldRefAccess<ContactsDialog, Dictionary<string, ContactItem>>("_contactItems");
private static readonly FieldRef<ContactsDialog, List<ContactItem>> SearchResults = AccessTools.FieldRefAccess<ContactsDialog, List<ContactItem>>("_searchResultItems");
internal static readonly FieldRef<ContactsDialog, bool> SortRequested = AccessTools.FieldRefAccess<ContactsDialog, bool>("sortList");
private static readonly FieldRef<ContactsDialog, SyncRef<TextField>> Search = AccessTools.FieldRefAccess<ContactsDialog, SyncRef<TextField>>("_searchBar");
private static readonly FieldRef<ContactsDialog, UIBuilder> ListUI = AccessTools.FieldRefAccess<ContactsDialog, UIBuilder>("listUi");
internal static void BindSettings(ConfigFile config)
{
BatchSize = config.Bind<int>("Loading", "Batch size", 5, "Maximum contacts to create or restore per batch. Values below 1 are treated as 1. Applies to the next batch.");
PauseUpdates = config.Bind<int>("Loading", "Updates to skip", 1, "Updates to skip between batches. 0 or less runs every update. Decreases shorten the current wait; increases apply after the next batch. No restart required.");
}
internal static void Apply(Harmony harmony)
{
MethodInfo val = Target("OnAttach", global::System.Array.Empty<global::System.Type>());
MethodInfo val2 = Target("OnCommonUpdate", global::System.Array.Empty<global::System.Type>());
MethodInfo val3 = Target("OnActivated", global::System.Array.Empty<global::System.Type>());
MethodInfo val4 = Target("UpdateContactItem", new global::System.Type[1] { typeof(ContactData) });
MethodInfo val5 = Target("OpenContactPage", new global::System.Type[1] { typeof(string) });
MethodInfo val6 = Target("set_SelectedContactId", new global::System.Type[1] { typeof(string) });
MethodInfo val7 = Target("SearchTextChanged", new global::System.Type[1] { typeof(TextEditor) });
MethodInfo val8 = Target("OnDispose", global::System.Array.Empty<global::System.Type>());
Enumerable.ToList<CodeInstruction>(TranspileAttach((global::System.Collections.Generic.IEnumerable<CodeInstruction>)PatchProcessor.GetOriginalInstructions((MethodBase)(object)val, (ILGenerator)null)));
Enumerable.ToList<CodeInstruction>(TranspileSort((global::System.Collections.Generic.IEnumerable<CodeInstruction>)PatchProcessor.GetOriginalInstructions((MethodBase)(object)val2, (ILGenerator)null), (MethodBase)(object)val2));
Enumerable.ToList<CodeInstruction>(TranspileSort((global::System.Collections.Generic.IEnumerable<CodeInstruction>)PatchProcessor.GetOriginalInstructions((MethodBase)(object)val3, (ILGenerator)null), (MethodBase)(object)val3));
Enumerable.ToList<CodeInstruction>(TranspileSort((global::System.Collections.Generic.IEnumerable<CodeInstruction>)PatchProcessor.GetOriginalInstructions((MethodBase)(object)val4, (ILGenerator)null), (MethodBase)(object)val4));
Enumerable.ToList<CodeInstruction>(TranspileSearch((global::System.Collections.Generic.IEnumerable<CodeInstruction>)PatchProcessor.GetOriginalInstructions((MethodBase)(object)val7, (ILGenerator)null)));
harmony.Patch((MethodBase)(object)val, (HarmonyMethod)null, (HarmonyMethod)null, Patch("TranspileAttach"), (HarmonyMethod)null, (HarmonyMethod)null);
harmony.Patch((MethodBase)(object)val2, (HarmonyMethod)null, (HarmonyMethod)null, Patch("TranspileSort"), (HarmonyMethod)null, (HarmonyMethod)null);
harmony.Patch((MethodBase)(object)val3, (HarmonyMethod)null, (HarmonyMethod)null, Patch("TranspileSort"), (HarmonyMethod)null, (HarmonyMethod)null);
harmony.Patch((MethodBase)(object)val4, Patch("BeforeItem"), (HarmonyMethod)null, Patch("TranspileSort"), (HarmonyMethod)null, (HarmonyMethod)null);
harmony.Patch((MethodBase)(object)val5, Patch("BeforeSelect"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
harmony.Patch((MethodBase)(object)val6, Patch("BeforeSelect"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
harmony.Patch((MethodBase)(object)val7, Patch("BeforeSearch"), (HarmonyMethod)null, Patch("TranspileSearch"), (HarmonyMethod)null, (HarmonyMethod)null);
harmony.Patch((MethodBase)(object)val8, Patch("OnDispose"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
[CompilerGenerated]
static HarmonyMethod Patch(string name)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
return new HarmonyMethod(typeof(ContactsPatches), name, (global::System.Type[])null);
}
[CompilerGenerated]
static MethodInfo Target(string name, params global::System.Type[] parameters)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
return AccessTools.DeclaredMethod(typeof(ContactsDialog), name, parameters, (global::System.Type[])null) ?? throw new MissingMethodException(typeof(ContactsDialog).FullName, name);
}
}
internal static global::System.Collections.Generic.IEnumerable<CodeInstruction> TranspileAttach(global::System.Collections.Generic.IEnumerable<CodeInstruction> instructions)
{
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00e0: 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_0134: 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_0157: Unknown result type (might be due to invalid IL or missing references)
List<CodeInstruction> val = Enumerable.ToList<CodeInstruction>(instructions);
MethodInfo enumerate = AccessTools.Method(typeof(ContactManager), "ForeachContactData", (global::System.Type[])null, (global::System.Type[])null);
ValueTuple<CodeInstruction, int>[] array = Enumerable.ToArray<ValueTuple<CodeInstruction, int>>(Enumerable.Where<ValueTuple<CodeInstruction, int>>(Enumerable.Select<CodeInstruction, ValueTuple<CodeInstruction, int>>((global::System.Collections.Generic.IEnumerable<CodeInstruction>)val, (Func<CodeInstruction, int, ValueTuple<CodeInstruction, int>>)((CodeInstruction op, int index) => new ValueTuple<CodeInstruction, int>(op, index))), (Func<ValueTuple<CodeInstruction, int>, bool>)((ValueTuple<CodeInstruction, int> p) => CodeInstructionExtensions.Calls(p.Item1, enumerate))));
if (array.Length != 1)
{
throw new InvalidOperationException($"Expected one initial contact enumeration call; found {array.Length}.");
}
int item = array[0].Item2;
if (item >= 3 && !(val[item - 3].opcode != OpCodes.Ldarg_0) && !(val[item - 2].opcode != OpCodes.Ldftn))
{
object operand = val[item - 2].operand;
MethodInfo val2 = (MethodInfo)((operand is MethodInfo) ? operand : null);
if (val2 != null && !((MethodBase)val2).IsStatic && !(((MemberInfo)val2).DeclaringType != typeof(ContactsDialog)) && !(val[item - 1].opcode != OpCodes.Newobj))
{
val[item].opcode = OpCodes.Call;
val[item].operand = AccessTools.Method(typeof(ContactsPatches), "Start", (global::System.Type[])null, (global::System.Type[])null);
return (global::System.Collections.Generic.IEnumerable<CodeInstruction>)val;
}
}
throw new InvalidOperationException("The initial contact callback has an unexpected format.");
}
internal static global::System.Collections.Generic.IEnumerable<CodeInstruction> TranspileSort(global::System.Collections.Generic.IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
{
//IL_0096: 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_008d: Unknown result type (might be due to invalid IL or missing references)
List<CodeInstruction> obj = Enumerable.ToList<CodeInstruction>(instructions);
FieldInfo field = AccessTools.Field(typeof(ContactsDialog), "sortList");
bool writing = ((MemberInfo)__originalMethod).Name != "OnCommonUpdate";
CodeInstruction[] array = Enumerable.ToArray<CodeInstruction>(Enumerable.Where<CodeInstruction>((global::System.Collections.Generic.IEnumerable<CodeInstruction>)obj, (Func<CodeInstruction, bool>)((CodeInstruction op) => op.opcode == (writing ? OpCodes.Stfld : OpCodes.Ldfld) && object.Equals(op.operand, (object)field))));
if (array.Length != 1)
{
throw new InvalidOperationException($"Expected one sort flag access; found {array.Length}.");
}
array[0].opcode = OpCodes.Call;
array[0].operand = AccessTools.Method(typeof(ContactsPatches), (!writing) ? "UpdateLoading" : ((((MemberInfo)__originalMethod).Name == "OnActivated") ? "RequestActivationSort" : "RequestItemSort"), (global::System.Type[])null, (global::System.Type[])null);
return (global::System.Collections.Generic.IEnumerable<CodeInstruction>)obj;
}
internal static global::System.Collections.Generic.IEnumerable<CodeInstruction> TranspileSearch(global::System.Collections.Generic.IEnumerable<CodeInstruction> instructions)
{
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: 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_00c2: 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)
List<CodeInstruction> val = Enumerable.ToList<CodeInstruction>(instructions);
MethodInfo target = AccessTools.PropertySetter(typeof(Slot), "ActiveSelf");
ValueTuple<CodeInstruction, int>[] array = Enumerable.ToArray<ValueTuple<CodeInstruction, int>>(Enumerable.Where<ValueTuple<CodeInstruction, int>>(Enumerable.Select<CodeInstruction, ValueTuple<CodeInstruction, int>>((global::System.Collections.Generic.IEnumerable<CodeInstruction>)val, (Func<CodeInstruction, int, ValueTuple<CodeInstruction, int>>)((CodeInstruction op, int i) => new ValueTuple<CodeInstruction, int>(op, i))), (Func<ValueTuple<CodeInstruction, int>, bool>)((ValueTuple<CodeInstruction, int> p) => CodeInstructionExtensions.Calls(p.Item1, target))));
if (array.Length != 2)
{
throw new InvalidOperationException("The search visibility updates have an unexpected format.");
}
ValueTuple<CodeInstruction, int> val2 = array[0];
CodeInstruction item = val2.Item1;
int item2 = val2.Item2;
if (item2 == 0 || val[item2 - 1].opcode != OpCodes.Ldc_I4_1)
{
throw new InvalidOperationException("The search reset activation has an unexpected format.");
}
val[item2 - 1].opcode = OpCodes.Ldarg_0;
item.opcode = OpCodes.Call;
item.operand = AccessTools.Method(typeof(ContactsPatches), "QueueRestore", (global::System.Type[])null, (global::System.Type[])null);
return (global::System.Collections.Generic.IEnumerable<CodeInstruction>)val;
}
internal static ValueTuple<int, int, long, string> SortKey(Contact contact, OnlineStatus status, bool unread)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Invalid comparison between Unknown and I4
//IL_001a: 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_0032: Expected I4, but got Unknown
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
int num;
if (contact.IsPartiallyMigrated)
{
num = 10;
}
else
{
int num2 = (((int)contact.ContactStatus != 2) ? ((status - 2) switch
{
3 => 0,
2 => 1,
0 => 3,
1 => 4,
_ => 5,
}) : 2);
num = num2;
}
int num3 = num;
return new ValueTuple<int, int, long, string>((!unread) ? 1 : 0, num3, -contact.LatestMessageTime.Ticks, contact.ContactUsername);
}
internal static ValueTuple<List<ContactData>, Dictionary<string, int>> Prepare(List<ContactData> snapshot, Func<ContactData, int> unreadCount)
{
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
ValueTuple<ContactData, ValueTuple<int, int, long, string>>[] array = Enumerable.ToArray<ValueTuple<ContactData, ValueTuple<int, int, long, string>>>((global::System.Collections.Generic.IEnumerable<ValueTuple<ContactData, ValueTuple<int, int, long, string>>>)Enumerable.OrderBy<ValueTuple<ContactData, ValueTuple<int, int, long, string>>, ValueTuple<int, int, long, string>>(Enumerable.Select<ContactData, ValueTuple<ContactData, ValueTuple<int, int, long, string>>>((global::System.Collections.Generic.IEnumerable<ContactData>)snapshot, (Func<ContactData, ValueTuple<ContactData, ValueTuple<int, int, long, string>>>)delegate(ContactData data)
{
//IL_0024: 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_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: 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)
Contact contact = data.Contact;
UserStatus currentStatus = data.CurrentStatus;
OnlineStatus valueOrDefault = ((currentStatus != null) ? currentStatus.OnlineStatus : ((OnlineStatus?)null)).GetValueOrDefault();
int num = unreadCount.Invoke(data);
return new ValueTuple<ContactData, ValueTuple<int, int, long, string>>(data, SortKey(contact, valueOrDefault, num > 0));
}), (Func<ValueTuple<ContactData, ValueTuple<int, int, long, string>>, ValueTuple<int, int, long, string>>)((ValueTuple<ContactData, ValueTuple<int, int, long, string>> entry) => entry.Item2)));
return new ValueTuple<List<ContactData>, Dictionary<string, int>>(Enumerable.ToList<ContactData>(Enumerable.Select<ValueTuple<ContactData, ValueTuple<int, int, long, string>>, ContactData>((global::System.Collections.Generic.IEnumerable<ValueTuple<ContactData, ValueTuple<int, int, long, string>>>)array, (Func<ValueTuple<ContactData, ValueTuple<int, int, long, string>>, ContactData>)((ValueTuple<ContactData, ValueTuple<int, int, long, string>> entry) => entry.Item1))), Enumerable.ToDictionary<ValueTuple<string, int>, string, int>(Enumerable.Select<ValueTuple<ContactData, ValueTuple<int, int, long, string>>, ValueTuple<string, int>>((global::System.Collections.Generic.IEnumerable<ValueTuple<ContactData, ValueTuple<int, int, long, string>>>)array, (Func<ValueTuple<ContactData, ValueTuple<int, int, long, string>>, int, ValueTuple<string, int>>)((ValueTuple<ContactData, ValueTuple<int, int, long, string>> entry, int index) => new ValueTuple<string, int>(entry.Item1.UserId, index))), (Func<ValueTuple<string, int>, string>)((ValueTuple<string, int> entry) => entry.Item1), (Func<ValueTuple<string, int>, int>)((ValueTuple<string, int> entry) => entry.Item2)));
}
private static void Start(ContactManager manager, Action<ContactData> update)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Expected O, but got Unknown
<>c__DisplayClass18_0 CS$<>8__locals13 = new <>c__DisplayClass18_0();
CS$<>8__locals13.manager = manager;
object target = ((global::System.Delegate)(object)update).Target;
CS$<>8__locals13.dialog = (ContactsDialog)((target is ContactsDialog) ? target : null);
if (CS$<>8__locals13.dialog == null)
{
ReportError?.Invoke((global::System.Exception)new InvalidOperationException("Unexpected contact loading target; using the original enumeration."));
CS$<>8__locals13.manager.ForeachContactData(update);
return;
}
CS$<>8__locals13.state = new Loading(CS$<>8__locals13.manager, update);
Pending.Add(CS$<>8__locals13.dialog, CS$<>8__locals13.state);
SortRequested.Invoke(CS$<>8__locals13.dialog) = false;
CS$<>8__locals13.messages = ((SkyFrostInterface)((Worker)CS$<>8__locals13.dialog).Cloud).Messages;
((Worker)CS$<>8__locals13.dialog).StartTask((Func<global::System.Threading.Tasks.Task>)([AsyncStateMachine(typeof(<>c__DisplayClass18_0.<<Start>b__0>d))] () =>
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
<>c__DisplayClass18_0.<<Start>b__0>d <<Start>b__0>d = default(<>c__DisplayClass18_0.<<Start>b__0>d);
<<Start>b__0>d.<>t__builder = AsyncTaskMethodBuilder.Create();
<<Start>b__0>d.<>4__this = CS$<>8__locals13;
<<Start>b__0>d.<>1__state = -1;
((AsyncTaskMethodBuilder)(ref <<Start>b__0>d.<>t__builder)).Start<<>c__DisplayClass18_0.<<Start>b__0>d>(ref <<Start>b__0>d);
return ((AsyncTaskMethodBuilder)(ref <<Start>b__0>d.<>t__builder)).Task;
}));
}
private static void UpdateSpacer(ContactsDialog dialog, Loading state)
{
if (state.ReservedRows == 0)
{
return;
}
if (state.ReservedRows < 0)
{
state.ReservedRows = Enumerable.Count<ContactData>((global::System.Collections.Generic.IEnumerable<ContactData>)state.Contacts, (Func<ContactData, bool>)((ContactData data) => !data.Contact.ShouldBeHidden));
}
int num = state.ReservedRows - Items.Invoke(dialog).Count;
Slot root = ListUI.Invoke(dialog).Root;
VerticalLayout component = ((ContainerWorker<Component>)(object)root).GetComponent<VerticalLayout>((Predicate<VerticalLayout>)null, false);
if (num <= 0 || component == null)
{
state.ClearSpacer();
return;
}
if (state.Spacer == null)
{
state.Spacer = root.AddSlot("SmoothContacts Spacer", true);
state.Spacer.OrderOffset = 9223372036854775807L;
((ContainerWorker<Component>)(object)state.Spacer).AttachComponent<RectTransform>(true, (Action<RectTransform>)null);
((ContainerWorker<Component>)(object)state.Spacer).AttachComponent<LayoutElement>(true, (Action<LayoutElement>)null);
}
float value = ((SyncField<float>)(object)((DirectionalLayout)component).Spacing).Value;
float num2 = (float)num * (32f + value) - value;
LayoutElement component2 = ((ContainerWorker<Component>)(object)state.Spacer).GetComponent<LayoutElement>((Predicate<LayoutElement>)null, false);
Sync<float> minHeight = component2.MinHeight;
float value2 = (((SyncField<float>)(object)component2.PreferredHeight).Value = num2);
((SyncField<float>)(object)minHeight).Value = value2;
}
internal static bool UpdateLoading(ContactsDialog dialog)
{
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_0222: Unknown result type (might be due to invalid IL or missing references)
//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
Loading loading = default(Loading);
bool flag = Pending.TryGetValue(dialog, ref loading);
PriorityQueue<ContactItem, long> val = default(PriorityQueue<ContactItem, long>);
bool flag2 = Restoring.TryGetValue(dialog, ref val);
if (!flag && !flag2)
{
return SortRequested.Invoke(dialog);
}
int num = Math.Max(1, BatchSize.Value);
int num2 = num;
StrongBox<int> value = Pauses.GetValue(dialog, (CreateValueCallback<ContactsDialog, StrongBox<int>>)((ContactsDialog _) => new StrongBox<int>()));
try
{
if (loading?.Contacts != null)
{
string selection = loading.Selection;
if (selection != null)
{
loading.Selection = null;
dialog.OpenContactPage(selection);
}
}
value.Value = Math.Min(value.Value, Math.Max(0, PauseUpdates.Value));
if (value.Value > 0)
{
value.Value--;
return !flag && SortRequested.Invoke(dialog);
}
if (flag2)
{
ContactItem val2 = default(ContactItem);
long num3 = default(long);
while (num2 > 0 && val.TryDequeue(ref val2, ref num3))
{
num2--;
try
{
if (!((Worker)val2).IsRemoved && !((Component)val2).Slot.ActiveSelf)
{
((Component)val2).Slot.ActiveSelf = true;
}
}
catch (global::System.Exception ex)
{
ReportError?.Invoke(ex);
}
}
if (val.Count == 0)
{
Restoring.Remove(dialog);
}
}
if (!flag)
{
return SortRequested.Invoke(dialog);
}
if (loading.Contacts == null)
{
return false;
}
string term = NormalizeQuery(Search.Invoke(dialog).Target.TargetString);
if (loading.Position == loading.Contacts.Count)
{
Enumerator<string, ContactData> enumerator = loading.Deferred.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
KeyValuePair<string, ContactData> current = enumerator.Current;
loading.Order[current.Key] = loading.Contacts.Count;
loading.Contacts.Add(current.Value);
}
}
finally
{
((global::System.IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
}
loading.Deferred.Clear();
}
ValueTuple<int, int> val3 = loading.TakeBatch(num2);
int item = val3.Item1;
int item2 = val3.Item2;
num2 -= item2 - item;
for (int num4 = item; num4 < item2; num4++)
{
Generate(dialog, loading, loading.Contacts[num4], term);
}
if (loading.Position == loading.Contacts.Count && loading.Deferred.Count == 0)
{
EndLoading(dialog);
}
else
{
UpdateSpacer(dialog, loading);
}
}
catch (global::System.Exception error)
{
Abort(dialog, error);
}
finally
{
if (num2 < num)
{
value.Value = Math.Max(0, PauseUpdates.Value);
}
Loading loading2 = default(Loading);
PriorityQueue<ContactItem, long> val4 = default(PriorityQueue<ContactItem, long>);
if (!Pending.TryGetValue(dialog, ref loading2) && !Restoring.TryGetValue(dialog, ref val4))
{
Pauses.Remove(dialog);
}
}
return false;
}
internal static void Generate(ContactsDialog dialog, Loading state, ContactData data, string term)
{
ContactData val = default(ContactData);
if (state.Deferred.Remove(data.UserId, ref val))
{
data = val;
}
if (Items.Invoke(dialog).ContainsKey(data.UserId) || state.manager.GetContact(data.UserId) != data.Contact)
{
return;
}
state.Creating = true;
try
{
state.update.Invoke(data);
ContactItem val2 = default(ContactItem);
if (Items.Invoke(dialog).TryGetValue(data.UserId, ref val2))
{
((Component)val2).Slot.OrderOffset = state.RowOrder(data.UserId);
if (term.Length > 0 && !MatchesSearch(val2.Username, val2.AlternateNames, term))
{
((Component)val2).Slot.ActiveSelf = false;
}
}
}
finally
{
state.Creating = false;
}
}
internal static bool BeforeSelect(ContactsDialog __instance, string __0)
{
Loading loading = default(Loading);
if (string.IsNullOrEmpty(__0) || !Pending.TryGetValue(__instance, ref loading))
{
return true;
}
loading.Selection = null;
if (Items.Invoke(__instance).ContainsKey(__0) || Enumerable.Any<ContactItem>((global::System.Collections.Generic.IEnumerable<ContactItem>)SearchResults.Invoke(__instance), (Func<ContactItem, bool>)((ContactItem item) => item.Contact.ContactUserId == __0)))
{
return true;
}
if (loading.Contacts == null || !((Component)__instance).Slot.IsActive)
{
loading.Selection = __0;
return false;
}
try
{
ContactData data = null;
int num = default(int);
if (loading.Order.TryGetValue(__0, ref num))
{
data = loading.Contacts[num];
}
else
{
loading.manager.ForeachContactData((Action<ContactData>)delegate(ContactData candidate)
{
if (candidate.UserId == __0)
{
data = candidate;
}
});
}
if (data != null)
{
Generate(__instance, loading, data, NormalizeQuery(Search.Invoke(__instance).Target.TargetString));
}
if (Items.Invoke(__instance).ContainsKey(__0))
{
UpdateSpacer(__instance, loading);
}
else
{
loading.ClearSpacer();
}
}
catch (global::System.Exception error)
{
Abort(__instance, error);
throw;
}
return true;
}
internal static bool BeforeItem(ContactsDialog __instance, ContactData __0)
{
Loading loading = default(Loading);
if (Pending.TryGetValue(__instance, ref loading) && !loading.Creating && !Items.Invoke(__instance).ContainsKey(__0.UserId))
{
loading.Deferred[__0.UserId] = __0;
SortRequested.Invoke(__instance) = true;
return false;
}
return true;
}
internal static void BeforeSearch(ContactsDialog __instance)
{
Restoring.Remove(__instance);
Pauses.Remove(__instance);
Loading loading = default(Loading);
if (Pending.TryGetValue(__instance, ref loading))
{
loading.ClearSpacer();
}
}
internal static void QueueRestore(Slot slot, ContactsDialog dialog)
{
if (!slot.ActiveSelf)
{
Restoring.GetValue(dialog, (CreateValueCallback<ContactsDialog, PriorityQueue<ContactItem, long>>)((ContactsDialog _) => new PriorityQueue<ContactItem, long>())).Enqueue(((ContainerWorker<Component>)(object)slot).GetComponent<ContactItem>((Predicate<ContactItem>)null, false), slot.OrderOffset);
}
}
internal static string NormalizeQuery(string? query)
{
return query?.Trim().ToLower() ?? "";
}
internal static bool MatchesSearch(string username, global::System.Collections.Generic.IEnumerable<string> alternateNames, string term)
{
if (term.Length == 0)
{
return true;
}
if (username.StartsWith(term, (StringComparison)3))
{
return true;
}
global::System.Collections.Generic.IEnumerator<string> enumerator = alternateNames.GetEnumerator();
try
{
while (((global::System.Collections.IEnumerator)enumerator).MoveNext())
{
if (enumerator.Current.StartsWith(term, (StringComparison)2))
{
return true;
}
}
}
finally
{
((global::System.IDisposable)enumerator)?.Dispose();
}
return false;
}
internal static void RequestActivationSort(ContactsDialog dialog, bool requested)
{
Loading loading = default(Loading);
if (!Pending.TryGetValue(dialog, ref loading))
{
SortRequested.Invoke(dialog) = requested;
}
}
internal static void RequestItemSort(ContactsDialog dialog, bool requested)
{
Loading loading = default(Loading);
if (!Pending.TryGetValue(dialog, ref loading) || !loading.Creating)
{
SortRequested.Invoke(dialog) = requested;
}
}
private static void Abort(ContactsDialog dialog, global::System.Exception error)
{
EndLoading(dialog);
SortRequested.Invoke(dialog) = true;
ReportError?.Invoke(error);
}
private static void EndLoading(ContactsDialog dialog)
{
Loading loading = default(Loading);
if (Pending.TryGetValue(dialog, ref loading))
{
loading.ClearSpacer();
}
Pending.Remove(dialog);
}
internal static void OnDispose(ContactsDialog __instance)
{
EndLoading(__instance);
Restoring.Remove(__instance);
Pauses.Remove(__instance);
}
}