Files
Net.Like.Xue.Tokyo/Packages-Local/Com.Project.B.Unity/PDA/Feed/AppFeed.cs

264 lines
8.9 KiB
C#
Raw Normal View History

2025-06-24 23:49:13 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using BITKit;
using BITKit.StateMachine;
using BITKit.UX;
using Cysharp.Threading.Tasks;
using Net.Project.B.World;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UIElements;
namespace Net.Project.B.PDA.App
{
[Serializable]
public struct Feed : IApp
{
public string PackageName => "com.bndroid.feed";
public string AppName => "动态";
}
public record AppFeedItem
{
public string UserName;
public string Content;
public string[] ImageNames;
public DateTime Timestamp;
public int LikeCount;
public int Rewards;
}
public class AppFeed: PDAApp<Feed>
{
protected override string DocumentPath => "ui_app_feed";
private readonly IDictionary<Guid, AppFeedItem> _database;
private readonly ISnapshotService _snapshotService;
[UXBindPath("feed-container")]
private VisualElement _feedContainer;
[UXBindPath("image-selection")]
private VisualElement _imageSelection;
[UXBindPath("image-selected")]
private VisualElement _imageSelected;
[UXBindPath("select-images")]
private Button _selectImageButton;
[UXBindPath("confirm-images-button")]
private Button _confirmImageButton;
[UXBindPath("cancel-images-button")]
private Button _cancelImageButton;
[UXBindPath("feed-field")]
private TextField _feedField;
[UXBindPath("release-button")]
private Button _releaseButton;
private VisualTreeAsset _imageTemplate;
private VisualTreeAsset _feedTemplate;
private readonly HashSet<SnapshotData> _selectedImages = new();
private readonly HashSet<SnapshotData> _releaseImages = new();
private CancellationTokenSource _homeCts = new();
public AppFeed(IDictionary<Guid, AppFeedItem> database, ISnapshotService snapshotService)
{
_database = database;
_snapshotService = snapshotService;
}
private async void Home()
{
RootVisualElement.Q("SelectImage").SetActive(false);
_homeCts.Cancel();
_homeCts = new CancellationTokenSource();
_feedContainer.Clear();
foreach (var (guid,item) in _database.OrderByDescending(x=>x.Value.Timestamp))
{
var container = _feedContainer.Create(_feedTemplate);
container.Get<Label>().text = item.UserName;
container.Get<Label>(1).text = item.Content;
var likes = container.Get<Label>(2);
likes.text = item.LikeCount.ToString();
container.Get<Button>().clicked += () =>
{
item.LikeCount++;
likes.text = item.LikeCount.ToString();
};
container.Get<Label>(5).text = item.Timestamp.ToString(CultureInfo.InvariantCulture);
var imageContainer = container.Get<VisualElement>(1);
imageContainer.Clear();
var reward = container.Get<IntegerField>();
var rewardButton = container.Get<Button>(1);
var rewardLabel = container.Get<Label>(3);
rewardLabel.text = item.Rewards.ToString();
rewardButton.clicked += () =>
{
item.Rewards += reward.value;
reward.value = 0;
rewardLabel.text = item.Rewards.ToString();
};
foreach (var imageName in item.ImageNames)
{
var ve = imageContainer.Create(_imageTemplate);
using var handle = UnityWebRequestTexture.GetTexture($"file://" + imageName);
await handle.SendWebRequest();
if(_homeCts.IsCancellationRequested)return;
var texture = DownloadHandlerTexture.GetContent(handle);
ve.Get<VisualElement>().style.backgroundImage = new StyleBackground(texture);
}
}
}
private void New()
{
foreach (var x in _imageSelection.Children())
{
if(x.userData is not SnapshotData snapshotData)continue;
if (_releaseImages.Contains(snapshotData))
{
x.AddToClassList("selected");
}
else
{
x.RemoveFromClassList("selected");
}
}
}
public override void Initialize()
{
base.Initialize();
_confirmImageButton.clicked += New;
_cancelImageButton.clicked += New;
_confirmImageButton.clicked += async () =>
{
_releaseImages.Clear();
_releaseImages.UnionWith(_selectedImages);
_imageSelected.Clear();
foreach (var snapshotData in _releaseImages)
{
var ve = _imageSelected.Create(_imageTemplate);
using var handle = UnityWebRequestTexture.GetTexture($"file://" + snapshotData.FileName);
await handle.SendWebRequest();
var texture = DownloadHandlerTexture.GetContent(handle);
ve.Get<VisualElement>().style.backgroundImage = new StyleBackground(texture);
ve.RegisterCallback<PointerDownEvent>(x =>
{
if (_selectedImages.Remove(snapshotData))
{
ve.RemoveFromHierarchy();
}
});
}
};
_imageTemplate = _imageSelection.Q<TemplateContainer>().templateSource;
_imageSelection.Clear();
_feedTemplate = _feedContainer.Q<TemplateContainer>().templateSource;
_feedContainer.Clear();
_releaseButton.clicked += Release;
_releaseButton.clicked += Home;
_selectImageButton.clicked += () => RootVisualElement.Q("SelectImage").SetActive(true);
RootVisualElement.Q("SelectImage").SetActive(false);
Home();
}
private void Release()
{
var data = new AppFeedItem
{
Content = _feedField.text,
ImageNames = _selectedImages.Select(x => x.FileName).ToArray(),
Timestamp = DateTime.Now,
LikeCount = 0,
UserName = Environment.UserName
};
_database.Add(Guid.NewGuid(),data);
_selectedImages.Clear();
_imageSelected.Clear();
_feedField.value = string.Empty;
foreach (var x in _imageSelection.Children())
{
x.RemoveFromClassList("selected");
}
}
public override async UniTask OnStateEntryAsync(IState old)
{
await base.OnStateEntryAsync(old);
_imageSelection.Clear();
_imageSelected.Clear();
_selectedImages.Clear();
foreach (var snapshotData in (await _snapshotService.GetSnapshots()).OrderByDescending(x=>x.CreateTime))
{
if(File.Exists(snapshotData.FileName) is false)continue;
var ve = _imageSelection.Create(_imageTemplate);
await UniTask.SwitchToMainThread();
using var handle = UnityWebRequestTexture.GetTexture($"file://" + snapshotData.FileName);
await handle.SendWebRequest();
var texture = DownloadHandlerTexture.GetContent(handle);
ve.Get<VisualElement>().style.backgroundImage = new StyleBackground(texture);
ve.userData = snapshotData;
ve.RegisterCallback<PointerDownEvent>(x =>
{
if (_selectedImages.Add(snapshotData) is false)
{
_selectedImages.Remove(snapshotData);
}
ve.ToggleInClassList("selected");
});
}
}
public override UniTask<object> GetPage(string route)
{
var path = route.Split("/").Last();
Debug.Log(path);
return base.GetPage(route);
}
}
}