/**
* Copyright 2019 The Knights Of Unity, created by Piotr Stoch
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Nakama;
using System;
using System.Threading.Tasks;
using DemoGame.Scripts.Session;
namespace DemoGame.Scripts.Friends
{
public class UsernameSearcher : MonoBehaviour
{
///
/// Struct used for capsulating user search results loaded from database
///
private struct SearchResult
{
public string[] usernames;
public SearchResult(string[] usernames)
{
this.usernames = usernames;
}
}
#region public events
public event Action OnSubmit = delegate { };
#endregion
#region public properties
///
/// Returns current value of searcher input field
///
public string InputFieldValue
{
get
{
return _inputField.text;
}
}
#endregion
#region private serialized fields
[SerializeField] private GameObject _usernameTipPrefab = null;
[Header("UI elements")]
[SerializeField] private InputField _inputField = null;
[SerializeField] private RectTransform _usernameTipsParent = null;
#endregion
#region private fields
///
/// All search tasks running in this moment
///
private List _actualTasks = new List();
///
/// Tips showed for matching usernames
///
private List _tips = new List();
#endregion
#region mono
private void Start()
{
//connecting button clicks to methods
_inputField.onValueChanged.AddListener(SearchUsers);
_inputField.onEndEdit.AddListener(SearchEnded);
_inputField.onEndEdit.AddListener(Submit);
}
#endregion
#region public methods
///
/// Sets immadiatelly searcher text in input field
///
///
public void SetSearcherText(string username)
{
_inputField.onValueChanged.RemoveListener(SearchUsers);
_inputField.text = username;
_inputField.onValueChanged.AddListener(SearchUsers);
DeleteAllTips();
}
#endregion
#region private methods
///
/// Checks if editing was ended with return key
///
///
public void Submit(string value)
{
if (!string.IsNullOrEmpty(value))
{
if (Input.GetKeyDown(KeyCode.Return))
{
OnSubmit();
}
}
}
///
/// Search for users matching name requirements
///
///
private async void SearchUsers(string text)
{
//dont search when text is empty
if (string.IsNullOrEmpty(text))
{
return;
}
//client and session shortcuts
Client client = NakamaSessionManager.Instance.Client;
ISession session = NakamaSessionManager.Instance.Session;
//nakama rpc method parameter
string payload = text;
//rpc method id from server
string rpcid = "search_username";
try
{
//creating search task - sending request for running "search_username" method on server with text parameter
Task searchTask = client.RpcAsync(session, rpcid, payload);
//adding this search task to list
_actualTasks.Add(searchTask);
//awaiting for server returning value
IApiRpc searchResult = await searchTask;
Debug.Log(searchResult.Payload);
//unpacking results to SearchResult struct object
SearchResult result = JsonUtility.FromJson(searchResult.Payload);
//checking if its last currently running search task
if (_actualTasks.Count == 1)
{
DeleteAllTips();
//creating tip for first 5 matched usernames
for (int i = 0; i < 5 && i < result.usernames.Length; i++)
{
if (!string.IsNullOrEmpty(result.usernames[i]))
{
CreateTip(result.usernames[i]);
}
}
}
//removing task from actual tasks list
_actualTasks.Remove(searchTask);
}
catch (Exception e)
{
Debug.LogError("Could not search users (" + e.Message + ")");
}
}
#region showing and removing tips
///
/// Instaties and initializes tip basing on loaded username
///
///
private void CreateTip(string username)
{
GameObject go = Instantiate(_usernameTipPrefab, _usernameTipsParent);
UsernameTip tip = go.GetComponent();
if (tip)
{
tip.Init(username, this);
_tips.Add(tip);
}
else
{
Debug.LogError("Invalid username tip prefab!");
Destroy(go);
}
}
///
/// Invoked when user has ended interaction with .
///
///
private void SearchEnded(string value)
{
// Calculate tips parent screen rect
Rect tipParentRect = _usernameTipsParent.rect;
tipParentRect.position += (Vector2)_usernameTipsParent.position;
// Check if mouse within tips parent
if (tipParentRect.Contains(Input.mousePosition) == false)
{
DeleteAllTips();
}
}
///
/// Destroys all showed tips
///
private void DeleteAllTips()
{
for (int i = 0; i < _tips.Count; i++)
{
Destroy(_tips[i].gameObject, 0.1f);
}
_tips.Clear();
}
#endregion
#endregion
}
}