本地记录重新上传,一些界面bug修复
This commit is contained in:
parent
470d52b1bc
commit
f1eeb11543
2808
Assets/Resources/UI/Prefab/ResultList/LocalRouteItem.prefab
Normal file
2808
Assets/Resources/UI/Prefab/ResultList/LocalRouteItem.prefab
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 27d66dc2cf0c0944da1bb3dd00e0e721
|
||||||
|
PrefabImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
File diff suppressed because it is too large
Load Diff
@ -329,8 +329,8 @@ public class CyclingController : DeviceServiceMonoBase
|
|||||||
{
|
{
|
||||||
item.IsShowInfo = false;
|
item.IsShowInfo = false;
|
||||||
}
|
}
|
||||||
var frontPlayer = others.Where(c => c.TotalDistance - playerController.TotalDistance < 0.5 && c.TotalDistance - playerController.TotalDistance >= 0 && !(c is PlayerController)).OrderBy(c=>c.TotalDistance).FirstOrDefault();
|
var frontPlayer = others.Where(c => c.TotalDistance - playerController.TotalDistance < 0.25 && c.TotalDistance - playerController.TotalDistance >= 0 && !(c is PlayerController)).OrderBy(c=>c.TotalDistance).FirstOrDefault();
|
||||||
var bakePlayer = others.Where(c => c.TotalDistance - playerController.TotalDistance >-0.5 && c.TotalDistance - playerController.TotalDistance < 0 && !(c is PlayerController)).OrderByDescending(c=>c.TotalDistance).FirstOrDefault();
|
var bakePlayer = others.Where(c => c.TotalDistance - playerController.TotalDistance >-0.25 && c.TotalDistance - playerController.TotalDistance < 0 && !(c is PlayerController)).OrderByDescending(c=>c.TotalDistance).FirstOrDefault();
|
||||||
if(frontPlayer != null)
|
if(frontPlayer != null)
|
||||||
frontPlayer.IsShowInfo = true;
|
frontPlayer.IsShowInfo = true;
|
||||||
if (bakePlayer != null)
|
if (bakePlayer != null)
|
||||||
|
|||||||
@ -10,36 +10,61 @@ namespace Assets.Scenes.Ride.Scripts
|
|||||||
public class NumberDotween:MonoBehaviour
|
public class NumberDotween:MonoBehaviour
|
||||||
{
|
{
|
||||||
private Sequence mScoreSequence;
|
private Sequence mScoreSequence;
|
||||||
|
private Sequence mProgressSequence;
|
||||||
private Text text;
|
private Text text;
|
||||||
private float mOldScore = 0;
|
private float mOldScore = 0;
|
||||||
|
private float mOldScoreNew = 0;
|
||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
//函数内初始化
|
//函数内初始化
|
||||||
mScoreSequence = DOTween.Sequence();
|
mScoreSequence = DOTween.Sequence();
|
||||||
|
mProgressSequence = DOTween.Sequence();
|
||||||
//函数内设置属性
|
//函数内设置属性
|
||||||
mScoreSequence.SetAutoKill(false);
|
mScoreSequence.SetAutoKill(false);
|
||||||
|
mProgressSequence.SetAutoKill(false);
|
||||||
text = transform.GetComponent<Text>();
|
text = transform.GetComponent<Text>();
|
||||||
}
|
}
|
||||||
private double temp = 0;
|
private double temp = 0;
|
||||||
private int index = -1;
|
private int index = -1;
|
||||||
|
private int indexNew = -1;
|
||||||
public void AnimateNum(float newScore,double totalDistance,int currentIndex, int digit, string format,Image process)
|
public void AnimateNum(float newScore,double totalDistance,int currentIndex, int digit, string format,Image process)
|
||||||
{
|
{
|
||||||
if (currentIndex != index)
|
if (currentIndex != indexNew)
|
||||||
{
|
{
|
||||||
text.text = string.Format(format, totalDistance);
|
indexNew = currentIndex;
|
||||||
index = currentIndex;
|
|
||||||
process.fillAmount = 1;
|
process.fillAmount = 1;
|
||||||
StartCoroutine(CompleteFill(process));
|
StartCoroutine(CompleteFill(process));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
mProgressSequence.Append(DOTween.To(delegate (float value)
|
||||||
|
{
|
||||||
|
process.fillAmount = (float)(value / totalDistance);
|
||||||
|
}, mOldScoreNew, newScore, 1f));
|
||||||
|
//将更新后的值记录下来, 用于下一次滚动动画
|
||||||
|
mOldScoreNew = newScore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AnimateNumText(float newScore, double totalDistance, int currentIndex, int digit, string format, Image process)
|
||||||
|
{
|
||||||
|
if (currentIndex != index)
|
||||||
|
{
|
||||||
|
text.text = string.Format(format, totalDistance);
|
||||||
|
index = currentIndex;
|
||||||
|
mOldScore = (float)totalDistance;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
mScoreSequence.Append(DOTween.To(delegate (float value)
|
mScoreSequence.Append(DOTween.To(delegate (float value)
|
||||||
{
|
{
|
||||||
temp = Math.Round(value, digit);
|
//if (value != newScore)
|
||||||
process.fillAmount = (float)(value / totalDistance);
|
{
|
||||||
//向Text组件赋值
|
temp = Math.Round(value, digit);
|
||||||
text.text = string.Format(format, temp);
|
//向Text组件赋值
|
||||||
|
text.text = string.Format(format, temp);
|
||||||
|
}
|
||||||
}, mOldScore, newScore, 1f));
|
}, mOldScore, newScore, 1f));
|
||||||
//将更新后的值记录下来, 用于下一次滚动动画
|
//将更新后的值记录下来, 用于下一次滚动动画
|
||||||
mOldScore = newScore;
|
mOldScore = newScore;
|
||||||
@ -48,7 +73,7 @@ namespace Assets.Scenes.Ride.Scripts
|
|||||||
IEnumerator CompleteFill(Image process)
|
IEnumerator CompleteFill(Image process)
|
||||||
{
|
{
|
||||||
yield return new WaitForSeconds(0.3f);
|
yield return new WaitForSeconds(0.3f);
|
||||||
mOldScore = 0;
|
mOldScoreNew = 0;
|
||||||
process.fillAmount = 0;
|
process.fillAmount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -168,10 +168,10 @@ namespace Assets.Scenes.Ride.Scripts
|
|||||||
{
|
{
|
||||||
if (infoPanel == null)
|
if (infoPanel == null)
|
||||||
return;
|
return;
|
||||||
|
_directionsGO?.Destroy();
|
||||||
infoPanel.transform.GetComponent<CanvasGroup>().DOFade(0, 1).onComplete += () => {
|
infoPanel.transform.GetComponent<CanvasGroup>().DOFade(0, 1).onComplete += () => {
|
||||||
IsShowInfo = false;
|
IsShowInfo = false;
|
||||||
infoPanel?.Destroy();
|
infoPanel?.Destroy();
|
||||||
_directionsGO?.Destroy();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -157,10 +157,10 @@ namespace Assets.Scenes.Ride.Scripts
|
|||||||
{
|
{
|
||||||
if (infoPanel == null)
|
if (infoPanel == null)
|
||||||
return;
|
return;
|
||||||
|
_directionsGO?.Destroy();
|
||||||
infoPanel.transform.GetComponent<CanvasGroup>().DOFade(0, 1).onComplete += () => {
|
infoPanel.transform.GetComponent<CanvasGroup>().DOFade(0, 1).onComplete += () => {
|
||||||
IsShowInfo = false;
|
IsShowInfo = false;
|
||||||
infoPanel?.Destroy();
|
infoPanel?.Destroy();
|
||||||
_directionsGO?.Destroy();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -403,42 +403,31 @@ namespace Assets.Scenes.Ride.Scripts
|
|||||||
nextSlopeDistanceText.text = $"{Math.Round(playerController.NextSlopeTotalDistance, 0)}M";
|
nextSlopeDistanceText.text = $"{Math.Round(playerController.NextSlopeTotalDistance, 0)}M";
|
||||||
currentSlopeText.text = Math.Round(playerController.CurrentSlope, 1).ToString() + "%";
|
currentSlopeText.text = Math.Round(playerController.CurrentSlope, 1).ToString() + "%";
|
||||||
currentSlopeDistanceText.GetComponent<NumberDotween>().AnimateNum((float)playerController.CurrentSlopeDistance, Math.Round(playerController.CurrentDistance, 0), playerController.CurrentIndex, 0, "{0}M", currentSlopeProcess);
|
currentSlopeDistanceText.GetComponent<NumberDotween>().AnimateNum((float)playerController.CurrentSlopeDistance, Math.Round(playerController.CurrentDistance, 0), playerController.CurrentIndex, 0, "{0}M", currentSlopeProcess);
|
||||||
|
currentSlopeDistanceText.GetComponent<NumberDotween>().AnimateNumText((float)playerController.CurrentDistance - (float)playerController.CurrentSlopeDistance, Math.Round(playerController.CurrentDistance, 0), playerController.CurrentIndex, 0, "{0}M", currentSlopeProcess);
|
||||||
totalClimb.text = Math.Round(playerController.TotalClimb, 0).ToString();
|
totalClimb.text = Math.Round(playerController.TotalClimb, 0).ToString();
|
||||||
//小地图进度
|
//小地图进度
|
||||||
var process = (float)(playerController.TotalDistance / routeInstance.Distance);
|
var process = (float)(playerController.TotalDistance / routeInstance.Distance);
|
||||||
miniMapProcess.fillAmount = process;
|
miniMapProcess.fillAmount = process;
|
||||||
miniMapProcessText.text = $"{process*100:f0}%";
|
miniMapProcessText.text = $"{process*100:f0}%";
|
||||||
//动态改变坡度图片
|
//动态改变坡度图片
|
||||||
ChangeSlopeImage();
|
ChangeSlopeImage(nextSlopeImage, playerController.NextSlope);
|
||||||
|
ChangeSlopeImage(currentSlopeImage, playerController.CurrentSlope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ChangeSlopeImage()
|
private void ChangeSlopeImage(Image image,double slope)
|
||||||
{
|
{
|
||||||
if (playerController.CurrentSlope >= 1)
|
if (slope >= 1)
|
||||||
{
|
{
|
||||||
currentSlopeImage.sprite = uphill1;
|
image.sprite = uphill1;
|
||||||
}
|
}
|
||||||
else if (playerController.CurrentSlope > -1 || playerController.CurrentSlope < 1)
|
else if (slope > -1 && slope < 1)
|
||||||
{
|
{
|
||||||
currentSlopeImage.sprite = straight;
|
image.sprite = straight;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
currentSlopeImage.sprite = downhill1;
|
image.sprite = downhill1;
|
||||||
}
|
|
||||||
//下一个坡度
|
|
||||||
if (playerController.NextSlope >= 1)
|
|
||||||
{
|
|
||||||
nextSlopeImage.sprite = uphill1Small;
|
|
||||||
}
|
|
||||||
else if (playerController.NextSlope > -1 || playerController.NextSlope < 1)
|
|
||||||
{
|
|
||||||
nextSlopeImage.sprite = straightSmall;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nextSlopeImage.sprite = downhill1Small;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//重置游戏
|
//重置游戏
|
||||||
|
|||||||
139
Assets/Scripts/UI/Prefab/ResultList/LocalRouteItem.cs
Normal file
139
Assets/Scripts/UI/Prefab/ResultList/LocalRouteItem.cs
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
using Assets.Scripts;
|
||||||
|
using Assets.Scripts.Apis.Models;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.EventSystems;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using Assets.Scripts.Apis;
|
||||||
|
using Assets.Scenes.Ride.Scripts;
|
||||||
|
|
||||||
|
public class LocalRouteItem : MonoBehaviour, IPointerExitHandler, IPointerEnterHandler
|
||||||
|
{
|
||||||
|
MapInterruptRecord record;
|
||||||
|
// Start is called before the first frame update
|
||||||
|
Transform left,row1,row2,right;
|
||||||
|
Transform btnReRide, btnContinue, btnDelete;
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update is called once per frame
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
string titleColor = "#5c5c6e";
|
||||||
|
RouteResult data;
|
||||||
|
//滑动索引 0route 1match
|
||||||
|
int index;
|
||||||
|
List<string> listFileName = new List<string>();
|
||||||
|
string path;
|
||||||
|
public void Initial(string path,int index)
|
||||||
|
{
|
||||||
|
this.path = path;
|
||||||
|
this.index = index;
|
||||||
|
var Name = transform.Find("Left/Main/Name").GetComponent<Text>();
|
||||||
|
var Time = transform.Find("Left/Main/Time").GetComponent<Text>();
|
||||||
|
var RidingTime = transform.Find("Left/Main/Row1/Time").GetComponent<Text>();
|
||||||
|
var RidingDistance = transform.Find("Left/Main/Row1/Distance").GetComponent<Text>();
|
||||||
|
var Device = transform.Find("Left/Main/Row2/Device").GetComponent<Text>();
|
||||||
|
var recordImage = transform.Find("CoverImage").GetComponent<RawImage>();
|
||||||
|
var uploadBtn = transform.Find("Right/BtnContinue").GetComponent<Button>();
|
||||||
|
var deleteBtn = transform.Find("Right/BtnDelete").GetComponent<Button>();
|
||||||
|
UIManager.AddEvent(uploadBtn.gameObject, EventTriggerType.PointerClick, (b) => GoUplaod());
|
||||||
|
UIManager.AddEvent(deleteBtn.gameObject, EventTriggerType.PointerClick, (b) => GoDelete());
|
||||||
|
var fileList = Directory.GetFiles(path);
|
||||||
|
foreach (var item in fileList)
|
||||||
|
{
|
||||||
|
var fileInfo = new FileInfo(item);
|
||||||
|
//显示封面图片
|
||||||
|
if (fileInfo.Extension.ToLower().Equals(".png"))
|
||||||
|
{
|
||||||
|
var fileStream = fileInfo.OpenRead();
|
||||||
|
fileStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
byte[] bytes = new byte[fileStream.Length];
|
||||||
|
fileStream.Read(bytes, 0, (int)fileStream.Length);
|
||||||
|
fileStream.Close();
|
||||||
|
fileStream.Dispose();
|
||||||
|
Texture2D texture = new Texture2D(800, 450);
|
||||||
|
texture.LoadImage(bytes);
|
||||||
|
recordImage.texture = texture;
|
||||||
|
}
|
||||||
|
//显示骑行记录实体
|
||||||
|
if (fileInfo.Name.Equals("record.txt"))
|
||||||
|
{
|
||||||
|
var recordStr = File.ReadAllText(item);
|
||||||
|
record = Newtonsoft.Json.JsonConvert.DeserializeObject<MapInterruptRecord>(recordStr);
|
||||||
|
Name.text = record.RouteName;
|
||||||
|
Time.text = record.StartTime.ToString();
|
||||||
|
RidingTime.text = $"<color={titleColor}>Riding time:</color>{record.Ticks}";
|
||||||
|
RidingDistance.text = $"<color={titleColor}>Mileage:</color>{record.EndDistance.ToString("#0.00")}KM";
|
||||||
|
Device.text = $"<color={titleColor}>Cycling equipment:</color>{record.ManufacturerName}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
listFileName.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void GoUplaod()
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(path))
|
||||||
|
return;
|
||||||
|
UIManager.ShowConfirm("Upload", "Upload the local record?", () =>
|
||||||
|
{
|
||||||
|
MapInterruptRecordApi service = new MapInterruptRecordApi();
|
||||||
|
var result = service.Add(record, listFileName);
|
||||||
|
//删除文件
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UIManager.CloseConfirm();
|
||||||
|
if (result.result)
|
||||||
|
{
|
||||||
|
Helper.DelectDir(path);
|
||||||
|
DestroyImmediate(gameObject);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Utils.showToast(gameObject, result.errMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Utils.showToast(gameObject, e.Message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
void GoDelete()
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(path))
|
||||||
|
return;
|
||||||
|
UIManager.ShowConfirm("Delete", "Delete the local record?", () =>
|
||||||
|
{
|
||||||
|
//删除文件
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UIManager.CloseConfirm();
|
||||||
|
Helper.DelectDir(path);
|
||||||
|
DestroyImmediate(gameObject);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Utils.showToast(gameObject, e.Message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public void OnPointerExit(PointerEventData eventData)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public void OnPointerEnter(PointerEventData eventData)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Assets/Scripts/UI/Prefab/ResultList/LocalRouteItem.cs.meta
Normal file
11
Assets/Scripts/UI/Prefab/ResultList/LocalRouteItem.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b2305835a4128974baaed486343c2b37
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -4,6 +4,7 @@ using Assets.Scripts.Apis.Models;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
@ -11,6 +12,7 @@ using UnityEngine.UI;
|
|||||||
public class ResultListController : MonoBehaviour
|
public class ResultListController : MonoBehaviour
|
||||||
{
|
{
|
||||||
[SerializeField]Transform routeResult;
|
[SerializeField]Transform routeResult;
|
||||||
|
Transform localRouteItem;
|
||||||
Transform scrollContent;
|
Transform scrollContent;
|
||||||
Transform routeScroll, matchScroll;
|
Transform routeScroll, matchScroll;
|
||||||
Transform routeContent, matchContent;
|
Transform routeContent, matchContent;
|
||||||
@ -38,6 +40,7 @@ public class ResultListController : MonoBehaviour
|
|||||||
matchScroll = scrollContent.Find("MatchList");
|
matchScroll = scrollContent.Find("MatchList");
|
||||||
matchContent = matchScroll.Find("Viewport").Find("Content");
|
matchContent = matchScroll.Find("Viewport").Find("Content");
|
||||||
contents = new Transform[] { routeContent, matchContent};
|
contents = new Transform[] { routeContent, matchContent};
|
||||||
|
localRouteItem = Resources.Load<Transform>("UI/Prefab/ResultList/LocalRouteItem");
|
||||||
if (btnMatch != null)
|
if (btnMatch != null)
|
||||||
{
|
{
|
||||||
UIManager.AddEvent(btnMatch.gameObject, EventTriggerType.PointerClick, (b) =>
|
UIManager.AddEvent(btnMatch.gameObject, EventTriggerType.PointerClick, (b) =>
|
||||||
@ -161,8 +164,10 @@ public class ResultListController : MonoBehaviour
|
|||||||
{
|
{
|
||||||
isEnd[index] = false;
|
isEnd[index] = false;
|
||||||
DisplayRouteResult(r.data, contents[index],index);
|
DisplayRouteResult(r.data, contents[index],index);
|
||||||
|
DisplayLocalRouteResult(contents[index], index);//显示本地未上传成功的记录
|
||||||
scroll.transform.Find("Error").gameObject.SetActive(false);
|
scroll.transform.Find("Error").gameObject.SetActive(false);
|
||||||
//DisplayRouteResult(r.data, matchContent);
|
//DisplayRouteResult(r.data, matchContent);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -184,6 +189,30 @@ public class ResultListController : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void DisplayLocalRouteResult(Transform content, int index)
|
||||||
|
{
|
||||||
|
//查询本地上传失败的文件
|
||||||
|
var parentPath = PFConstants.MapWorkoutRecordFolder;
|
||||||
|
var dirList = Directory.GetDirectories(parentPath);
|
||||||
|
foreach (var item in dirList)
|
||||||
|
{
|
||||||
|
if (Directory.Exists(item))
|
||||||
|
{
|
||||||
|
var d = new DirectoryInfo(item);
|
||||||
|
//var createTime = d.CreationTime;//create time
|
||||||
|
//var newTime = createTime.AddSeconds(30D);
|
||||||
|
//if (newTime < DateTime.Now)
|
||||||
|
{
|
||||||
|
var obj = Instantiate(localRouteItem);
|
||||||
|
obj.GetComponent<LocalRouteItem>().Initial(item, 0);
|
||||||
|
obj.transform.parent = content;
|
||||||
|
obj.transform.localScale = new Vector3(1, 1, 1);
|
||||||
|
obj.SetAsFirstSibling();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void InitialColor()
|
void InitialColor()
|
||||||
{
|
{
|
||||||
ColorUtility.TryParseHtmlString("#FFFFFF", out c1);
|
ColorUtility.TryParseHtmlString("#FFFFFF", out c1);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user