Тема: Підскажіть паттерн обробки різних повідомлень і т.д.
Прів. Є купа повідомлень, кожне повідомлення має якийсь тип, і в залежності від типу повідомлення ми щось з ним робимо. Але є одна загальна риса цих повідомлень - всі вони додаються в один і той самий стек, і в проміжках між додаванням повідомлень в стек, потрібно показувати деяку картинку, котра повідомляє нам, що тіпо - будь-ласка, чекайте.
Також, перед додаванням повідомлення в стек, ми повинні почекати деякий час, і цей час залежить від довжини тексту в повідомленні, а якщо повідомлення не містить тексту, то ми чекаємо просто одну секунду.
Є повідомлення, котрі містять в собі лише картинку, в такому разі ми додаємо маленьку копію цієї картинки в стек, після чого зупиняємо весь цей конвеєр і збільшуємо іконку до розмірів оригінальної картинки, після цього, якщо користувач натисне на крестик, то ця збільшена іконка зникає і повідомлення надходять і далі.
А тепер проблема!
З самого початку кожне повідомлення я уявляв собі як окремий об'єкт, і тоді було все просто
foreach (var message in messages)
{
// показуємо картинку "пліз, чекайте на наступне повідомлення"
switch(message.type){
case TEXT:
//чекаємо деяку кількість часу
// додаємо повідомлення в стек
break;
case IMAGE:
//чекаємо деяку кількість часу
// додаємо іконку в стек
// збільшуємо іконку
// stop = true
// while(stop) {wait();}
// якщо десь там натиснули на певну кнопку, то stop=false і конвеєр пішов далі
break;
}
// ховаємо картинку "пліз, почекайте на наступне повідомлення"
// чекаємо пів секунди, чи десь так, аби ця картинка не з'являлася відразу після приховування
}
Але тепер вияснилось, що є цілі черги з повідомлень одного типу, тобто 10 разів підряд буде надходити повідомлення одного й того самого типу (повідомлення з текстом), і я вирішив зробити от таку стуктуру повідомлення
class Message{
public string text;
public string pathToImage;
public string[] messages; // ось тут масив з текстів
}
І коли надходить повідомлення, що містить текст, то я маю просто перевірити кількість об'єктів в масиві string[] messages, ну і якщо там щось є, то треба всі ці повідомлення додати в стек, при цьому тре вставляти затримки перед додаванням кожного повідомлення.
Як то все краще зробити? В мене була от така структура
foreach(var m in messages){
switch(m.type){
case Type1:
break;
case Type2:
break;
case Type3:
break;}
// а от тут різний код, котрий не залежить від типу повідомлення, наприклад, кожне повідомлення треба додати в стек, от тут може бути код додавання в стек, тому що йому пофіг на тип того повідомлення
}
А от зараз мені треба якось запихнути цикл додавання повідомлення в блок case, і тре то все зробити якось супер-гарно, аби код не повторювався ніде, от вам теперішній код.
Як то все зробити, щоб було гарно і оптимізовано?
IEnumerator StartChat(List<MessageData> messages)
{
// Debug.Log("start chat");
yield return new WaitForEndOfFrame();
MessageController mc = null;
GameObject go = null;
RectTransform rectTrans = null;
MessageImageController mic = null;
float timeToWait = 0;
int countToStop = 0;
foreach (var message in messages)
{
MessageType type = message.type;
countToStop++;
//yield return new WaitForSeconds(0.5f);
loaderToMove.transform.DOMoveX(loaderVisible.position.x, 0.2f);
if (message.text.Length < 20)
timeToWait = 1.5f;
else if (message.text.Length >= 20)
timeToWait = 2.5f;
else if (message.text.Length >= 50)
timeToWait = 3.5f;
else if (message.text.Length >= 80)
timeToWait = 4.5f;
else timeToWait = 1;
switch (type){
case MessageType.TEXT:
//continue;
if (message.name != oldName)
{
oldName = message.name;
side = !side;
}
if (side)
{
go = Instantiate(leftMessage, Vector2.zero, Quaternion.identity) as GameObject;
}
else
{
go = Instantiate(rightMessage, Vector2.zero, Quaternion.identity) as GameObject;
}
mc = go.GetComponent<MessageController>();
mc.messageType = message.type;
mc.Text = "<b>" + message.name + "</b>: " + message.text;
yield return new WaitForSeconds(timeToWait);
go.transform.SetParent(content.transform);
RefreshTrans(go.transform);
mc.SetSide(side);
this.messages.Add(mc);
break;
case MessageType.SYSTEM_CONNECTION_RESTORED:
//continue;
go = Instantiate(systemMessageConnectionR, Vector2.zero, Quaternion.identity) as GameObject;
yield return new WaitForSeconds(timeToWait);
go.transform.SetParent(content.transform);
RefreshTrans(go.transform);
this.messages.Add(mc);
break;
case MessageType.IMAGE:
go = Instantiate(imageMessage, Vector2.zero, Quaternion.identity) as GameObject;
mic = go.GetComponent<MessageImageController>();
var spriteMini = Resources.Load<Sprite>(message.imagePath);
var spriteFull = Resources.Load<Sprite>(message.imagePath.Replace("mini", ""));
mic.FullSprite = spriteFull;
imageVwr.sprite = spriteFull;
mic.Image = spriteMini;
mc = mic;
stopChat = true;
yield return new WaitForSeconds(timeToWait);
go.transform.SetParent(content.transform);
RefreshTrans(go.transform);
ScaleImage(mic);
while (stopChat)
{
yield return new WaitForEndOfFrame();
}
this.messages.Add(mc);
break;
case MessageType.BUTTON_SELECT_CHAR:
go = Instantiate(selectCharBtn, Vector2.zero, Quaternion.identity) as GameObject;
var mb = go.GetComponent<CanvasGroup>();
mb.DOFade(1, 3f);
yield return new WaitForSeconds(timeToWait);
go.transform.SetParent(content.transform);
RefreshTrans(go.transform);
this.messages.Add(mc);
break;
case MessageType.SYSTEM_MESSAGE:
go = Instantiate(systemMessage, Vector2.zero, Quaternion.identity) as GameObject;
yield return new WaitForSeconds(timeToWait);
go.transform.SetParent(content.transform);
RefreshTrans(go.transform);
this.messages.Add(mc);
break;
case MessageType.ADMIN_MESSAGE:
foreach(var str in message.messages)
{
go = Instantiate(adminMessage, Vector2.zero, Quaternion.identity) as GameObject;
mc = go.GetComponent<MessageController>();
mc.messageType = message.type;
string str1 = str.Replace("[b]", "<b>");
str1 = str1.Replace("[/b]", "</b>");
mc.Text = str1;
}
go.transform.SetParent(content.transform);
RefreshTrans(go.transform);
this.messages.Add(mc);
break;
}
loaderToMove.transform.DOMoveX(loaderHidden.position.x, 0.2f);
yield return new WaitForSeconds(0.6f);
}
}