Merge pull request #1106 from ONLYOFFICE/feature/socket-newtag
Feature/socket newtag
This commit is contained in:
commit
0d814ae191
@ -26,408 +26,92 @@
|
||||
|
||||
namespace ASC.Core.Notify.Socket;
|
||||
|
||||
[Scope]
|
||||
public class ConfigureSocketServiceClient : IConfigureNamedOptions<SocketServiceClient>
|
||||
{
|
||||
internal readonly TenantManager _tenantManager;
|
||||
internal readonly CoreSettings _coreSettings;
|
||||
internal readonly MachinePseudoKeys _machinePseudoKeys;
|
||||
internal readonly IConfiguration _configuration;
|
||||
internal readonly ILogger<SocketServiceClient> logger;
|
||||
internal readonly IHttpClientFactory _clientFactory;
|
||||
|
||||
public ConfigureSocketServiceClient(
|
||||
TenantManager tenantManager,
|
||||
CoreSettings coreSettings,
|
||||
MachinePseudoKeys machinePseudoKeys,
|
||||
IConfiguration configuration,
|
||||
ILogger<SocketServiceClient> logger,
|
||||
IHttpClientFactory clientFactory)
|
||||
{
|
||||
_tenantManager = tenantManager;
|
||||
_coreSettings = coreSettings;
|
||||
_machinePseudoKeys = machinePseudoKeys;
|
||||
_configuration = configuration;
|
||||
this.logger = logger;
|
||||
_clientFactory = clientFactory;
|
||||
}
|
||||
|
||||
public void Configure(string name, SocketServiceClient options)
|
||||
{
|
||||
options._logger = logger;
|
||||
options._hub = name.Trim('/');
|
||||
options._tenantManager = _tenantManager;
|
||||
options._coreSettings = _coreSettings;
|
||||
options._clientFactory = _clientFactory;
|
||||
options._sKey = _machinePseudoKeys.GetMachineConstant();
|
||||
options._url = _configuration["web:hub:internal"];
|
||||
options.EnableSocket = !string.IsNullOrEmpty(options._url);
|
||||
|
||||
try
|
||||
{
|
||||
var replaceSetting = _configuration["jabber:replace-domain"];
|
||||
if (!string.IsNullOrEmpty(replaceSetting))
|
||||
{
|
||||
options._jabberReplaceDomain = true;
|
||||
var q =
|
||||
replaceSetting.Split(new[] { "->" }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(s => s.Trim().ToLowerInvariant())
|
||||
.ToList();
|
||||
options._jabberReplaceFromDomain = q.ElementAt(0);
|
||||
options._jabberReplaceToDomain = q.ElementAt(1);
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
public void Configure(SocketServiceClient options)
|
||||
{
|
||||
Configure("default", options);
|
||||
}
|
||||
}
|
||||
|
||||
[Scope(typeof(ConfigureSocketServiceClient))]
|
||||
[Singletone]
|
||||
public class SocketServiceClient
|
||||
{
|
||||
private static readonly TimeSpan _timeout = TimeSpan.FromSeconds(1);
|
||||
internal ILogger<SocketServiceClient> _logger;
|
||||
private static DateTime _lastErrorTime;
|
||||
public bool EnableSocket { get; set; }
|
||||
internal byte[] _sKey;
|
||||
internal string _url;
|
||||
internal bool _jabberReplaceDomain;
|
||||
internal string _jabberReplaceFromDomain;
|
||||
internal string _jabberReplaceToDomain;
|
||||
private readonly TimeSpan _timeout = TimeSpan.FromSeconds(1);
|
||||
private DateTime _lastErrorTime;
|
||||
|
||||
private readonly IHttpClientFactory _clientFactory;
|
||||
private readonly ILogger<SocketServiceClient> _logger;
|
||||
private readonly bool _enableSocket;
|
||||
private readonly byte[] _sKey;
|
||||
private readonly string _url;
|
||||
|
||||
internal string _hub;
|
||||
public virtual string Hub { get => "default"; }
|
||||
|
||||
internal TenantManager _tenantManager;
|
||||
internal CoreSettings _coreSettings;
|
||||
internal IHttpClientFactory _clientFactory;
|
||||
|
||||
public SocketServiceClient() { }
|
||||
|
||||
public void SendMessage(string callerUserName, string calleeUserName, string messageText, int tenantId,
|
||||
string domain)
|
||||
{
|
||||
try
|
||||
{
|
||||
domain = ReplaceDomain(domain);
|
||||
var tenant = tenantId == -1
|
||||
? _tenantManager.GetTenant(domain)
|
||||
: _tenantManager.GetTenant(tenantId);
|
||||
var isTenantUser = callerUserName.Length == 0;
|
||||
var message = new MessageClass
|
||||
{
|
||||
UserName = isTenantUser ? tenant.GetTenantDomain(_coreSettings) : callerUserName,
|
||||
Text = messageText
|
||||
};
|
||||
|
||||
MakeRequest("send", new { tenantId = tenant.Id, callerUserName, calleeUserName, message, isTenantUser });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
public SocketServiceClient(
|
||||
ILogger<SocketServiceClient> logger,
|
||||
IHttpClientFactory clientFactory,
|
||||
MachinePseudoKeys mashinePseudoKeys,
|
||||
IConfiguration configuration)
|
||||
{
|
||||
_logger = logger;
|
||||
_clientFactory = clientFactory;
|
||||
_sKey = mashinePseudoKeys.GetMachineConstant();
|
||||
_url = configuration["web:hub:internal"];
|
||||
_enableSocket = !string.IsNullOrEmpty(_url);
|
||||
}
|
||||
|
||||
public void SendInvite(string chatRoomName, string calleeUserName, string domain)
|
||||
{
|
||||
try
|
||||
{
|
||||
domain = ReplaceDomain(domain);
|
||||
|
||||
var tenant = _tenantManager.GetTenant(domain);
|
||||
|
||||
var message = new MessageClass
|
||||
{
|
||||
UserName = tenant.GetTenantDomain(_coreSettings),
|
||||
Text = chatRoomName
|
||||
};
|
||||
|
||||
MakeRequest("sendInvite", new { tenantId = tenant.Id, calleeUserName, message });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendState(string from, byte state, int tenantId, string domain)
|
||||
{
|
||||
try
|
||||
{
|
||||
domain = ReplaceDomain(domain);
|
||||
|
||||
if (tenantId == -1)
|
||||
{
|
||||
tenantId = _tenantManager.GetTenant(domain).Id;
|
||||
}
|
||||
|
||||
MakeRequest("setState", new { tenantId, from, state });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendOfflineMessages(string callerUserName, List<string> users, int tenantId)
|
||||
{
|
||||
try
|
||||
{
|
||||
MakeRequest("sendOfflineMessages", new { tenantId, callerUserName, users });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendUnreadCounts(Dictionary<string, int> unreadCounts, string domain)
|
||||
{
|
||||
try
|
||||
{
|
||||
domain = ReplaceDomain(domain);
|
||||
|
||||
var tenant = _tenantManager.GetTenant(domain);
|
||||
|
||||
MakeRequest("sendUnreadCounts", new { tenantId = tenant.Id, unreadCounts });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendUnreadUsers(Dictionary<int, Dictionary<Guid, int>> unreadUsers)
|
||||
{
|
||||
try
|
||||
{
|
||||
MakeRequest("sendUnreadUsers", unreadUsers);
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendUnreadUser(int tenant, string userId, int count)
|
||||
{
|
||||
try
|
||||
{
|
||||
MakeRequest("updateFolders", new { tenant, userId, count });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendMailNotification(int tenant, string userId, MailNotificationState state)
|
||||
{
|
||||
try
|
||||
{
|
||||
MakeRequest("sendMailNotification", new { tenant, userId, state });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void EnqueueCall(string numberId, string callId, string agent)
|
||||
{
|
||||
try
|
||||
{
|
||||
MakeRequest("enqueue", new { numberId, callId, agent });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void IncomingCall(string callId, string agent)
|
||||
{
|
||||
try
|
||||
{
|
||||
MakeRequest("incoming", new { callId, agent });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void MissCall(string numberId, string callId, string agent)
|
||||
{
|
||||
try
|
||||
{
|
||||
MakeRequest("miss", new { numberId, callId, agent });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void Reload(string numberId, string agentId = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var numberRoom = _tenantManager.GetCurrentTenant().Id + numberId;
|
||||
MakeRequest("reload", new { numberRoom, agentId });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void StartEdit<T>(T fileId, string room)
|
||||
{
|
||||
try
|
||||
{
|
||||
MakeRequest("start-edit", new { room, fileId });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void StopEdit<T>(T fileId, string room)
|
||||
{
|
||||
try
|
||||
{
|
||||
MakeRequest("stop-edit", new { room, fileId });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateFile<T>(T fileId, string room, string data)
|
||||
{
|
||||
try
|
||||
{
|
||||
MakeRequest("create-file", new { room, fileId, data });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateFile<T>(T fileId, string room, string data)
|
||||
{
|
||||
try
|
||||
{
|
||||
MakeRequest("update-file", new { room, fileId, data });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteFile<T>(T fileId, string room)
|
||||
{
|
||||
try
|
||||
{
|
||||
MakeRequest("delete-file", new { room, fileId });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
}
|
||||
|
||||
public T GetAgent<T>(string numberId, List<Guid> contactsResponsibles)
|
||||
{
|
||||
try
|
||||
{
|
||||
return MakeRequest<T>("GetAgent", new { numberId, contactsResponsibles });
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
ProcessError(error);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
private string ReplaceDomain(string domain)
|
||||
{
|
||||
if (_jabberReplaceDomain && domain.EndsWith(_jabberReplaceFromDomain))
|
||||
{
|
||||
var place = domain.LastIndexOf(_jabberReplaceFromDomain);
|
||||
if (place >= 0)
|
||||
{
|
||||
return domain.Remove(place, _jabberReplaceFromDomain.Length).Insert(place, _jabberReplaceToDomain);
|
||||
}
|
||||
}
|
||||
|
||||
return domain;
|
||||
}
|
||||
|
||||
private void ProcessError(Exception e)
|
||||
{
|
||||
_logger.ErrorService(e);
|
||||
|
||||
if (e is HttpRequestException)
|
||||
{
|
||||
_lastErrorTime = DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
private string MakeRequest(string method, object data)
|
||||
public async Task<string> MakeRequest(string method, object data)
|
||||
{
|
||||
if (!IsAvailable())
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
try
|
||||
{
|
||||
var request = new HttpRequestMessage();
|
||||
request.Headers.Add("Authorization", CreateAuthToken());
|
||||
request.Method = HttpMethod.Post;
|
||||
request.RequestUri = new Uri(GetMethod(method));
|
||||
|
||||
var jsonData = JsonConvert.SerializeObject(data);
|
||||
_logger.DebugMakeRequest(method, jsonData);
|
||||
|
||||
request.Content = new StringContent(jsonData, Encoding.UTF8, "application/json");
|
||||
|
||||
var httpClient = _clientFactory.CreateClient();
|
||||
|
||||
//async
|
||||
using (var response = await httpClient.SendAsync(request))
|
||||
using (var stream = await response.Content.ReadAsStreamAsync())
|
||||
using (var streamReader = new StreamReader(stream))
|
||||
{
|
||||
return await streamReader.ReadToEndAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorService(e);
|
||||
|
||||
if (e is HttpRequestException)
|
||||
{
|
||||
_lastErrorTime = DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var request = new HttpRequestMessage();
|
||||
request.Headers.Add("Authorization", CreateAuthToken());
|
||||
request.Method = HttpMethod.Post;
|
||||
request.RequestUri = new Uri(GetMethod(method));
|
||||
|
||||
var jsonData = JsonConvert.SerializeObject(data);
|
||||
_logger.DebugMakeRequest(method, jsonData);
|
||||
|
||||
request.Content = new StringContent(jsonData, Encoding.UTF8, "application/json");
|
||||
|
||||
var httpClient = _clientFactory.CreateClient();
|
||||
|
||||
using (var response = httpClient.Send(request))
|
||||
using (var stream = response.Content.ReadAsStream())
|
||||
using (var streamReader = new StreamReader(stream))
|
||||
{
|
||||
return streamReader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private T MakeRequest<T>(string method, object data)
|
||||
public async Task<T> MakeRequest<T>(string method, object data)
|
||||
{
|
||||
var resultMakeRequest = MakeRequest(method, data);
|
||||
var resultMakeRequest = await MakeRequest(method, data);
|
||||
|
||||
return JsonConvert.DeserializeObject<T>(resultMakeRequest);
|
||||
}
|
||||
|
||||
private bool IsAvailable()
|
||||
{
|
||||
return EnableSocket && _lastErrorTime + _timeout < DateTime.Now;
|
||||
return _enableSocket && _lastErrorTime + _timeout < DateTime.Now;
|
||||
}
|
||||
|
||||
private string GetMethod(string method)
|
||||
{
|
||||
return $"{_url.TrimEnd('/')}/controller/{_hub}/{method}";
|
||||
return $"{_url.TrimEnd('/')}/controller/{Hub}/{method}";
|
||||
}
|
||||
|
||||
public string CreateAuthToken(string pkey = "socketio")
|
||||
private string CreateAuthToken(string pkey = "socketio")
|
||||
{
|
||||
using var hasher = new HMACSHA1(_sKey);
|
||||
var now = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
|
||||
|
@ -26,5 +26,15 @@
|
||||
res.end();
|
||||
});
|
||||
|
||||
router.post("/markasnew-file", (req, res) => {
|
||||
files.markAsNewFile(req.body);
|
||||
res.end();
|
||||
});
|
||||
|
||||
router.post("/markasnew-folder", (req, res) => {
|
||||
files.markAsNewFolder(req.body);
|
||||
res.end();
|
||||
});
|
||||
|
||||
return router;
|
||||
};
|
||||
|
@ -55,32 +55,12 @@
|
||||
);
|
||||
});
|
||||
|
||||
socket.on("subscribe", (roomParts) => {
|
||||
if (!roomParts) return;
|
||||
|
||||
if (Array.isArray(roomParts)) {
|
||||
const rooms = roomParts.map((p) => getRoom(p));
|
||||
logger.info(`client ${socket.id} join rooms [${rooms.join(",")}]`);
|
||||
socket.join(rooms);
|
||||
} else {
|
||||
const room = getRoom(roomParts);
|
||||
logger.info(`client ${socket.id} join room ${room}`);
|
||||
socket.join(room);
|
||||
}
|
||||
socket.on("subscribe", ({roomParts, individual}) => {
|
||||
changeSubscription(roomParts, individual, subscribe);
|
||||
});
|
||||
|
||||
socket.on("unsubscribe", (roomParts) => {
|
||||
if (!roomParts) return;
|
||||
|
||||
if (Array.isArray(roomParts)) {
|
||||
const rooms = roomParts.map((p) => getRoom(p));
|
||||
logger.info(`client ${socket.id} leave rooms [${rooms.join(",")}]`);
|
||||
socket.leave(rooms);
|
||||
} else {
|
||||
const room = getRoom(roomParts);
|
||||
logger.info(`client ${socket.id} leave room ${room}`);
|
||||
socket.leave(room);
|
||||
}
|
||||
socket.on("unsubscribe", ({roomParts, individual}) => {
|
||||
changeSubscription(roomParts, individual, unsubscribe);
|
||||
});
|
||||
|
||||
socket.on("refresh-folder", (folderId) => {
|
||||
@ -94,6 +74,49 @@
|
||||
logger.info(`restore backup in room ${room}`);
|
||||
socket.to(room).emit("restore-backup");
|
||||
});
|
||||
|
||||
function changeSubscription(roomParts, individual, changeFunc) {
|
||||
if (!roomParts) return;
|
||||
|
||||
changeFunc(roomParts);
|
||||
|
||||
if(individual){
|
||||
if (Array.isArray(roomParts)) {
|
||||
changeFunc(roomParts.map((p) => `${p}-${userId}`));
|
||||
} else {
|
||||
changeFunc(`${roomParts}-${userId}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function subscribe(roomParts) {
|
||||
if (!roomParts) return;
|
||||
|
||||
if (Array.isArray(roomParts)) {
|
||||
const rooms = roomParts.map((p) => getRoom(p));
|
||||
logger.info(`client ${socket.id} join rooms [${rooms.join(",")}]`);
|
||||
socket.join(rooms);
|
||||
} else {
|
||||
const room = getRoom(roomParts);
|
||||
logger.info(`client ${socket.id} join room ${room}`);
|
||||
socket.join(room);
|
||||
}
|
||||
}
|
||||
|
||||
function unsubscribe(roomParts) {
|
||||
if (!roomParts) return;
|
||||
|
||||
if (Array.isArray(roomParts)) {
|
||||
const rooms = roomParts.map((p) => getRoom(p));
|
||||
logger.info(`client ${socket.id} leave rooms [${rooms.join(",")}]`);
|
||||
socket.leave(rooms);
|
||||
} else {
|
||||
const room = getRoom(roomParts);
|
||||
logger.info(`client ${socket.id} leave room ${room}`);
|
||||
socket.leave(room);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function startEdit({ fileId, room } = {}) {
|
||||
@ -125,5 +148,15 @@
|
||||
modifyFolder(room, "delete", fileId, "file");
|
||||
}
|
||||
|
||||
return { startEdit, stopEdit, createFile, deleteFile, updateFile };
|
||||
function markAsNewFile({ fileId, count, room } = {}) {
|
||||
logger.info(`markAsNewFile ${fileId} in room ${room}:${count}`);
|
||||
filesIO.to(room).emit("s:markasnew-file", { fileId, count });
|
||||
}
|
||||
|
||||
function markAsNewFolder({ folderId, count, room } = {}) {
|
||||
logger.info(`markAsNewFolder ${folderId} in room ${room}:${count}`);
|
||||
filesIO.to(room).emit("s:markasnew-folder", { folderId, count });
|
||||
}
|
||||
|
||||
return { startEdit, stopEdit, createFile, deleteFile, updateFile, markAsNewFile, markAsNewFolder };
|
||||
};
|
||||
|
@ -200,7 +200,7 @@ public class FeedAggregatorService : FeedBaseService
|
||||
}
|
||||
}
|
||||
|
||||
_socketServiceClient.SendUnreadUsers(unreadUsers);
|
||||
await _socketServiceClient.MakeRequest("sendUnreadUsers", unreadUsers);
|
||||
|
||||
_logger.DebugTimeCollectingNews(DateTime.UtcNow - start);
|
||||
}
|
||||
|
@ -269,7 +269,7 @@ export default function withFileActions(WrappedFileItem) {
|
||||
selectTag,
|
||||
selectOption,
|
||||
onSelectItem,
|
||||
setNewBadgeCount,
|
||||
//setNewBadgeCount,
|
||||
openFileAction,
|
||||
uploadEmptyFolders,
|
||||
} = filesActionsStore;
|
||||
@ -356,7 +356,7 @@ export default function withFileActions(WrappedFileItem) {
|
||||
isTrashFolder: isRecycleBinFolder,
|
||||
getFolderInfo,
|
||||
viewAs,
|
||||
setNewBadgeCount,
|
||||
//setNewBadgeCount,
|
||||
isActive,
|
||||
inProgress,
|
||||
setBufferSelection,
|
||||
|
@ -202,7 +202,7 @@ const Shell = ({ items = [], page = "home", ...rest }) => {
|
||||
useEffect(() => {
|
||||
socketHelper.emit({
|
||||
command: "subscribe",
|
||||
data: "backup-restore",
|
||||
data: { roomParts: "backup-restore" }
|
||||
});
|
||||
socketHelper.on("restore-backup", () => {
|
||||
setPreparationPortalDialogVisible(true);
|
||||
|
@ -76,7 +76,7 @@ class NewFilesPanel extends React.Component {
|
||||
|
||||
this.props
|
||||
.markAsRead(folderIds, fileIds)
|
||||
.then(() => this.setNewBadgeCount())
|
||||
//.then(() => this.setNewBadgeCount())
|
||||
.then(() => {
|
||||
const { hasNew, refreshFiles } = this.props;
|
||||
|
||||
@ -171,33 +171,33 @@ class NewFilesPanel extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
setNewBadgeCount = () => {
|
||||
const {
|
||||
newFilesIds,
|
||||
updateFoldersBadge,
|
||||
updateFilesBadge,
|
||||
updateRootBadge,
|
||||
updateFolderBadge,
|
||||
pathParts,
|
||||
newFiles,
|
||||
} = this.props;
|
||||
// setNewBadgeCount = () => {
|
||||
// const {
|
||||
// newFilesIds,
|
||||
// updateFoldersBadge,
|
||||
// updateFilesBadge,
|
||||
// updateRootBadge,
|
||||
// updateFolderBadge,
|
||||
// pathParts,
|
||||
// newFiles,
|
||||
// } = this.props;
|
||||
|
||||
const { readingFiles } = this.state;
|
||||
// const { readingFiles } = this.state;
|
||||
|
||||
const filesCount = newFiles.filter(
|
||||
(f) => !readingFiles.includes(f.id.toString())
|
||||
).length;
|
||||
updateRootBadge(+newFilesIds[0], filesCount);
|
||||
// const filesCount = newFiles.filter(
|
||||
// (f) => !readingFiles.includes(f.id.toString())
|
||||
// ).length;
|
||||
// updateRootBadge(+newFilesIds[0], filesCount);
|
||||
|
||||
if (newFilesIds.length <= 1) {
|
||||
if (pathParts[0] === +newFilesIds[0]) {
|
||||
updateFoldersBadge();
|
||||
updateFilesBadge();
|
||||
}
|
||||
} else {
|
||||
updateFolderBadge(newFilesIds[newFilesIds.length - 1], filesCount);
|
||||
}
|
||||
};
|
||||
// if (newFilesIds.length <= 1) {
|
||||
// if (pathParts[0] === +newFilesIds[0]) {
|
||||
// updateFoldersBadge();
|
||||
// updateFilesBadge();
|
||||
// }
|
||||
// } else {
|
||||
// updateFolderBadge(newFilesIds[newFilesIds.length - 1], filesCount);
|
||||
// }
|
||||
//};
|
||||
|
||||
render() {
|
||||
//console.log("NewFiles panel render");
|
||||
@ -306,13 +306,13 @@ export default inject(
|
||||
addFileToRecentlyViewed,
|
||||
//setIsLoading,
|
||||
isLoading,
|
||||
updateFilesBadge,
|
||||
updateFolderBadge,
|
||||
updateFoldersBadge,
|
||||
//updateFilesBadge,
|
||||
//updateFolderBadge,
|
||||
//updateFoldersBadge,
|
||||
hasNew,
|
||||
refreshFiles,
|
||||
} = filesStore;
|
||||
const { updateRootBadge } = treeFoldersStore;
|
||||
//const { updateRootBadge } = treeFoldersStore;
|
||||
const { setMediaViewerData } = mediaViewerDataStore;
|
||||
const { getIcon, getFolderIcon } = settingsStore;
|
||||
const { markAsRead } = filesActionsStore;
|
||||
@ -341,10 +341,10 @@ export default inject(
|
||||
getFolderIcon,
|
||||
markAsRead,
|
||||
setNewFilesPanelVisible,
|
||||
updateRootBadge,
|
||||
updateFolderBadge,
|
||||
updateFoldersBadge,
|
||||
updateFilesBadge,
|
||||
// updateRootBadge,
|
||||
// updateFolderBadge,
|
||||
// updateFoldersBadge,
|
||||
// updateFilesBadge,
|
||||
|
||||
theme: auth.settingsStore.theme,
|
||||
hasNew,
|
||||
|
@ -196,24 +196,24 @@ class DialogsStore {
|
||||
this.setNewFilesIds(newIds);
|
||||
} else {
|
||||
newFilesPanelVisible = false;
|
||||
const {
|
||||
getRootFolder,
|
||||
updateRootBadge,
|
||||
treeFolders,
|
||||
} = this.treeFoldersStore;
|
||||
const { updateFolderBadge, updateFoldersBadge } = this.filesStore;
|
||||
// const {
|
||||
// getRootFolder,
|
||||
// updateRootBadge,
|
||||
// treeFolders,
|
||||
// } = this.treeFoldersStore;
|
||||
// const { updateFolderBadge, updateFoldersBadge } = this.filesStore;
|
||||
|
||||
if (item) {
|
||||
const { rootFolderType, id } = item;
|
||||
const rootFolder = getRootFolder(rootFolderType);
|
||||
updateRootBadge(rootFolder.id, item.new);
|
||||
updateFolderBadge(id, item.new);
|
||||
} else {
|
||||
const rootFolder = treeFolders.find((x) => x.id === +newIds[0]);
|
||||
updateRootBadge(rootFolder.id, rootFolder.new);
|
||||
if (this.selectedFolderStore.id === rootFolder.id)
|
||||
updateFoldersBadge();
|
||||
}
|
||||
// if (item) {
|
||||
// const { rootFolderType, id } = item;
|
||||
// const rootFolder = getRootFolder(rootFolderType);
|
||||
// updateRootBadge(rootFolder.id, item.new);
|
||||
// updateFolderBadge(id, item.new);
|
||||
// } else {
|
||||
// const rootFolder = treeFolders.find((x) => x.id === +newIds[0]);
|
||||
// updateRootBadge(rootFolder.id, rootFolder.new);
|
||||
// if (this.selectedFolderStore.id === rootFolder.id)
|
||||
// updateFoldersBadge();
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
this.setNewFilesIds(null);
|
||||
|
@ -1097,18 +1097,18 @@ class FilesActionStore {
|
||||
setConnectItem({ ...provider, ...capability });
|
||||
};
|
||||
|
||||
setNewBadgeCount = (item) => {
|
||||
const { getRootFolder, updateRootBadge } = this.treeFoldersStore;
|
||||
const { updateFileBadge, updateFolderBadge } = this.filesStore;
|
||||
const { rootFolderType, fileExst, id } = item;
|
||||
// setNewBadgeCount = (item) => {
|
||||
// const { getRootFolder, updateRootBadge } = this.treeFoldersStore;
|
||||
// const { updateFileBadge, updateFolderBadge } = this.filesStore;
|
||||
// const { rootFolderType, fileExst, id } = item;
|
||||
|
||||
const count = item.new ? item.new : 1;
|
||||
const rootFolder = getRootFolder(rootFolderType);
|
||||
updateRootBadge(rootFolder.id, count);
|
||||
// const count = item.new ? item.new : 1;
|
||||
// const rootFolder = getRootFolder(rootFolderType);
|
||||
// updateRootBadge(rootFolder.id, count);
|
||||
|
||||
if (fileExst) updateFileBadge(id);
|
||||
else updateFolderBadge(id, item.new);
|
||||
};
|
||||
// if (fileExst) updateFileBadge(id);
|
||||
// else updateFolderBadge(id, item.new);
|
||||
// };
|
||||
|
||||
markAsRead = (folderIds, fileIds, item) => {
|
||||
const {
|
||||
@ -1132,7 +1132,7 @@ class FilesActionStore {
|
||||
.then(() => {
|
||||
if (!item) return;
|
||||
|
||||
this.setNewBadgeCount(item);
|
||||
//this.setNewBadgeCount(item);
|
||||
|
||||
const { getFileIndex, updateFileStatus } = this.filesStore;
|
||||
|
||||
|
@ -118,7 +118,7 @@ class FilesStore {
|
||||
const { socketHelper, withPaging } = authStore.settingsStore;
|
||||
|
||||
socketHelper.on("s:modify-folder", async (opt) => {
|
||||
//console.log("Call s:modify-folder", opt);
|
||||
console.log("[WS] s:modify-folder", opt);
|
||||
|
||||
if (this.isLoading) return;
|
||||
|
||||
@ -130,7 +130,13 @@ class FilesStore {
|
||||
|
||||
const file = JSON.parse(opt?.data);
|
||||
|
||||
const newFiles = [file, ...this.files];
|
||||
if (this.selectedFolderStore.id !== file.folderId) return;
|
||||
|
||||
const fileInfo = await api.files.getFileInfo(file.id);
|
||||
|
||||
console.log("[WS] create new file", fileInfo.id, fileInfo.title);
|
||||
|
||||
const newFiles = [fileInfo, ...this.files];
|
||||
|
||||
if (newFiles.length > this.filter.pageCount && withPaging) {
|
||||
newFiles.pop(); // Remove last
|
||||
@ -147,6 +153,8 @@ class FilesStore {
|
||||
|
||||
this.getFileInfo(file.id); //this.setFile(file);
|
||||
|
||||
console.log("[WS] update file", file.id, file.title);
|
||||
|
||||
if (this.selection) {
|
||||
const foundIndex = this.selection?.findIndex(
|
||||
(x) => x.id === file.id
|
||||
@ -175,6 +183,12 @@ class FilesStore {
|
||||
const foundIndex = this.files.findIndex((x) => x.id === opt?.id);
|
||||
if (foundIndex == -1) return;
|
||||
|
||||
console.log(
|
||||
"[WS] delete file",
|
||||
this.files[foundIndex].id,
|
||||
this.files[foundIndex].title
|
||||
);
|
||||
|
||||
this.setFiles(
|
||||
this.files.filter((_, index) => {
|
||||
return index !== foundIndex;
|
||||
@ -212,16 +226,46 @@ class FilesStore {
|
||||
//);
|
||||
|
||||
if (this.selectedFolderStore.id == id) {
|
||||
console.log("[WS] refresh-folder", id);
|
||||
this.fetchFiles(id, this.filter);
|
||||
}
|
||||
});
|
||||
|
||||
socketHelper.on("s:markasnew-folder", ({ folderId, count }) => {
|
||||
console.log(`[WS] markasnew-folder ${folderId}:${count}`);
|
||||
|
||||
const foundIndex =
|
||||
folderId && this.folders.findIndex((x) => x.id === folderId);
|
||||
if (foundIndex == -1) return;
|
||||
|
||||
runInAction(() => {
|
||||
this.folders[foundIndex].new = count >= 0 ? count : 0;
|
||||
this.treeFoldersStore.fetchTreeFolders();
|
||||
});
|
||||
});
|
||||
|
||||
socketHelper.on("s:markasnew-file", ({ fileId, count }) => {
|
||||
console.log(`[WS] markasnew-file ${fileId}:${count}`);
|
||||
|
||||
const foundIndex = fileId && this.files.findIndex((x) => x.id === fileId);
|
||||
if (foundIndex == -1) return;
|
||||
|
||||
this.updateFileStatus(
|
||||
foundIndex,
|
||||
count > 0
|
||||
? this.files[foundIndex].fileStatus | FileStatus.IsNew
|
||||
: this.files[foundIndex].fileStatus & ~FileStatus.IsNew
|
||||
);
|
||||
this.treeFoldersStore.fetchTreeFolders();
|
||||
});
|
||||
|
||||
//WAIT FOR RESPONSES OF EDITING FILE
|
||||
socketHelper.on("s:start-edit-file", (id) => {
|
||||
//console.log(`Call s:start-edit-file (id=${id})`);
|
||||
const foundIndex = this.files.findIndex((x) => x.id === id);
|
||||
if (foundIndex == -1) return;
|
||||
|
||||
console.log(`[WS] s:start-edit-file`, id, this.files[foundIndex].title);
|
||||
|
||||
this.updateSelectionStatus(
|
||||
id,
|
||||
this.files[foundIndex].fileStatus | FileStatus.IsEditing,
|
||||
@ -235,10 +279,11 @@ class FilesStore {
|
||||
});
|
||||
|
||||
socketHelper.on("s:stop-edit-file", (id) => {
|
||||
console.log(`Call s:stop-edit-file (id=${id})`);
|
||||
const foundIndex = this.files.findIndex((x) => x.id === id);
|
||||
if (foundIndex == -1) return;
|
||||
|
||||
console.log(`[WS] s:stop-edit-file`, id, this.files[foundIndex].title);
|
||||
|
||||
this.updateSelectionStatus(
|
||||
id,
|
||||
this.files[foundIndex].fileStatus & ~FileStatus.IsEditing,
|
||||
@ -426,7 +471,10 @@ class FilesStore {
|
||||
if (this.files?.length > 0) {
|
||||
socketHelper.emit({
|
||||
command: "unsubscribe",
|
||||
data: this.files.map((f) => `FILE-${f.id}`),
|
||||
data: {
|
||||
roomParts: this.files.map((f) => `FILE-${f.id}`),
|
||||
individual: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -435,14 +483,43 @@ class FilesStore {
|
||||
if (this.files?.length > 0) {
|
||||
socketHelper.emit({
|
||||
command: "subscribe",
|
||||
data: this.files.map((f) => `FILE-${f.id}`),
|
||||
data: {
|
||||
roomParts: this.files.map((f) => `FILE-${f.id}`),
|
||||
individual: true,
|
||||
},
|
||||
});
|
||||
|
||||
this.files?.forEach((file) =>
|
||||
console.log("[WS] subscribe to file's changes", file.id, file.title)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
setFolders = (folders) => {
|
||||
const { socketHelper } = this.authStore.settingsStore;
|
||||
if (folders.length === 0 && this.folders.length === 0) return;
|
||||
|
||||
if (this.folders?.length > 0) {
|
||||
socketHelper.emit({
|
||||
command: "unsubscribe",
|
||||
data: {
|
||||
roomParts: this.folders.map((f) => `DIR-${f.id}`),
|
||||
individual: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
this.folders = folders;
|
||||
|
||||
if (this.folders?.length > 0) {
|
||||
socketHelper.emit({
|
||||
command: "subscribe",
|
||||
data: {
|
||||
roomParts: this.folders.map((f) => `DIR-${f.id}`),
|
||||
individual: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
getFileIndex = (id) => {
|
||||
@ -1637,27 +1714,27 @@ class FilesStore {
|
||||
if (folderIndex !== -1) this.folders[folderIndex] = folder;
|
||||
};
|
||||
|
||||
updateFolderBadge = (id, count) => {
|
||||
const folder = this.folders.find((x) => x.id === id);
|
||||
if (folder) folder.new -= count;
|
||||
};
|
||||
// updateFolderBadge = (id, count) => {
|
||||
// const folder = this.folders.find((x) => x.id === id);
|
||||
// if (folder) folder.new -= count;
|
||||
// };
|
||||
|
||||
updateFileBadge = (id) => {
|
||||
const file = this.files.find((x) => x.id === id);
|
||||
if (file) file.fileStatus = file.fileStatus & ~FileStatus.IsEditing;
|
||||
};
|
||||
// updateFileBadge = (id) => {
|
||||
// const file = this.files.find((x) => x.id === id);
|
||||
// if (file) file.fileStatus = file.fileStatus & ~FileStatus.IsEditing;
|
||||
// };
|
||||
|
||||
updateFilesBadge = () => {
|
||||
for (let file of this.files) {
|
||||
file.fileStatus = file.fileStatus & ~FileStatus.IsEditing;
|
||||
}
|
||||
};
|
||||
// updateFilesBadge = () => {
|
||||
// for (let file of this.files) {
|
||||
// file.fileStatus = file.fileStatus & ~FileStatus.IsEditing;
|
||||
// }
|
||||
// };
|
||||
|
||||
updateFoldersBadge = () => {
|
||||
for (let folder of this.folders) {
|
||||
folder.new = 0;
|
||||
}
|
||||
};
|
||||
// updateFoldersBadge = () => {
|
||||
// for (let folder of this.folders) {
|
||||
// folder.new = 0;
|
||||
// }
|
||||
// };
|
||||
|
||||
updateRoomPin = (item) => {
|
||||
const idx = this.folders.findIndex((folder) => folder.id === item);
|
||||
@ -2613,9 +2690,15 @@ class FilesStore {
|
||||
|
||||
const { socketHelper } = this.authStore.settingsStore;
|
||||
if (createdItem?.type == "file") {
|
||||
console.log(
|
||||
"[WS] subscribe to file's changes",
|
||||
createdItem.id,
|
||||
createdItem.title
|
||||
);
|
||||
|
||||
socketHelper.emit({
|
||||
command: "subscribe",
|
||||
data: `FILE-${createdItem.id}`,
|
||||
data: { roomParts: `FILE-${createdItem.id}`, individual: true },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -74,13 +74,16 @@ class SelectedFolderStore {
|
||||
const { socketHelper } = this.settingsStore;
|
||||
|
||||
if (this.id !== null) {
|
||||
socketHelper.emit({ command: "unsubscribe", data: `DIR-${this.id}` });
|
||||
socketHelper.emit({
|
||||
command: "unsubscribe",
|
||||
data: { roomParts: `DIR-${this.id}`, individual: true },
|
||||
});
|
||||
}
|
||||
|
||||
if (selectedFolder) {
|
||||
socketHelper.emit({
|
||||
command: "subscribe",
|
||||
data: `DIR-${selectedFolder.id}`,
|
||||
data: { roomParts: `DIR-${selectedFolder.id}`, individual: true },
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -56,16 +56,16 @@ class TreeFoldersStore {
|
||||
this.expandedPanelKeys = expandedPanelKeys;
|
||||
};
|
||||
|
||||
updateRootBadge = (id, count) => {
|
||||
const index = this.treeFolders.findIndex((x) => x.id === id);
|
||||
if (index < 0) return;
|
||||
// updateRootBadge = (id, count) => {
|
||||
// const index = this.treeFolders.findIndex((x) => x.id === id);
|
||||
// if (index < 0) return;
|
||||
|
||||
this.treeFolders = this.treeFolders.map((f, i) => {
|
||||
if (i !== index) return f;
|
||||
f.newItems -= count;
|
||||
return f;
|
||||
});
|
||||
};
|
||||
// this.treeFolders = this.treeFolders.map((f, i) => {
|
||||
// if (i !== index) return f;
|
||||
// f.newItems -= count;
|
||||
// return f;
|
||||
// });
|
||||
// };
|
||||
|
||||
isMy = (myType) => myType === FolderType.USER;
|
||||
isCommon = (commonType) => commonType === FolderType.COMMON;
|
||||
|
@ -44,7 +44,7 @@ const withDialogs = (WrappedComponent) => {
|
||||
const { socketHelper } = window.authStore.auth.settingsStore;
|
||||
socketHelper.emit({
|
||||
command: "subscribe",
|
||||
data: "backup-restore",
|
||||
data: { roomParts: "backup-restore" }
|
||||
});
|
||||
socketHelper.on("restore-backup", () => {
|
||||
const message = t("Common:PreparationPortalTitle");
|
||||
|
@ -42,7 +42,7 @@ public enum TagType
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[DebuggerDisplay("{TagName} ({Id}) entry {EntryType} ({EntryId})")]
|
||||
[DebuggerDisplay("{Name} ({Id}) entry {EntryType} ({EntryId})")]
|
||||
public sealed class Tag : IMapFrom<DbFilesTag>
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
@ -203,12 +203,20 @@ public class FileStorageService<T> //: IFileStorageService
|
||||
public async Task<Folder<T>> GetFolderAsync(T folderId)
|
||||
{
|
||||
var folderDao = GetFolderDao();
|
||||
var tagDao = GetTagDao();
|
||||
var folder = await folderDao.GetFolderAsync(folderId);
|
||||
|
||||
ErrorIf(folder == null, FilesCommonResource.ErrorMassage_FolderNotFound);
|
||||
ErrorIf(!await _fileSecurity.CanReadAsync(folder), FilesCommonResource.ErrorMassage_SecurityException_ReadFolder);
|
||||
|
||||
await _entryStatusManager.SetIsFavoriteFolderAsync(folder);
|
||||
|
||||
var tag = await tagDao.GetNewTagsAsync(_authContext.CurrentAccount.ID, folder).FirstOrDefaultAsync();
|
||||
if (tag != null)
|
||||
{
|
||||
folder.NewForMe = tag.Count;
|
||||
}
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
@ -968,7 +976,7 @@ public class FileStorageService<T> //: IFileStorageService
|
||||
if (isFinish)
|
||||
{
|
||||
_fileTracker.Remove(id, tabId);
|
||||
_socketManager.StopEdit(id);
|
||||
await _socketManager.StopEdit(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1018,7 +1026,7 @@ public class FileStorageService<T> //: IFileStorageService
|
||||
if (!forcesave && _fileTracker.IsEditingAlone(fileId))
|
||||
{
|
||||
_fileTracker.Remove(fileId);
|
||||
_socketManager.StopEdit(fileId);
|
||||
await _socketManager.StopEdit(fileId);
|
||||
}
|
||||
|
||||
var file = await _entryManager.SaveEditingAsync(fileId, fileExtension, fileuri, stream, doc, forcesave: forcesave ? ForcesaveType.User : ForcesaveType.None, keepLink: true);
|
||||
@ -1043,7 +1051,7 @@ public class FileStorageService<T> //: IFileStorageService
|
||||
if (!forcesave && _fileTracker.IsEditing(fileId))
|
||||
{
|
||||
_fileTracker.Remove(fileId);
|
||||
_socketManager.StopEdit(fileId);
|
||||
await _socketManager.StopEdit(fileId);
|
||||
}
|
||||
|
||||
var file = await _entryManager.SaveEditingAsync(fileId,
|
||||
|
@ -220,7 +220,7 @@ public class DocumentServiceTrackerHelper
|
||||
case TrackerStatus.NotFound:
|
||||
case TrackerStatus.Closed:
|
||||
_fileTracker.Remove(fileId);
|
||||
_socketManager.StopEdit(fileId);
|
||||
await _socketManager.StopEdit(fileId);
|
||||
|
||||
break;
|
||||
|
||||
@ -284,7 +284,6 @@ public class DocumentServiceTrackerHelper
|
||||
_logger.InformationDocServiceUserIdIsNotGuid(user);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
users.Remove(userId);
|
||||
|
||||
@ -314,7 +313,7 @@ public class DocumentServiceTrackerHelper
|
||||
_fileTracker.Remove(fileId, userId: removeUserId);
|
||||
}
|
||||
|
||||
_socketManager.StartEdit(fileId);
|
||||
await _socketManager.StartEdit(fileId);
|
||||
}
|
||||
|
||||
private async Task<TrackResponse> ProcessSaveAsync<T>(T fileId, TrackerData fileData)
|
||||
@ -438,7 +437,7 @@ public class DocumentServiceTrackerHelper
|
||||
if (!forcesave)
|
||||
{
|
||||
_fileTracker.Remove(fileId);
|
||||
_socketManager.StopEdit(fileId);
|
||||
await _socketManager.StopEdit(fileId);
|
||||
}
|
||||
|
||||
if (file != null)
|
||||
|
@ -104,7 +104,6 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
await DeleteFilesAsync(Files, scope, true);
|
||||
await DeleteFoldersAsync(Folders, scope, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private async Task DeleteFoldersAsync(IEnumerable<T> folderIds, IServiceScope scope, bool isNeedSendActions = false)
|
||||
@ -279,7 +278,7 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
}
|
||||
}
|
||||
|
||||
socketManager.DeleteFile(file);
|
||||
await socketManager.DeleteFile(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -299,7 +298,7 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
filesMessageService.Send(file, MessageInitiator.AutoCleanUp, MessageAction.FileDeleted, file.Title);
|
||||
}
|
||||
|
||||
socketManager.DeleteFile(file);
|
||||
await socketManager.DeleteFile(file);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -565,12 +565,12 @@ class FileMoveCopyOperation<T> : FileOperation<FileMoveCopyOperationData<T>, T>
|
||||
await LinkDao.DeleteAllLinkAsync(file.Id.ToString());
|
||||
}
|
||||
|
||||
if (Equals(toFolderId.ToString(), _daoFolderId))
|
||||
if (Equals(toFolderId, _daoFolderId))
|
||||
{
|
||||
needToMark.Add(newFile);
|
||||
}
|
||||
|
||||
socketManager.DeleteFile(file);
|
||||
await socketManager.DeleteFile(file);
|
||||
|
||||
await socketManager.CreateFileAsync(newFile);
|
||||
|
||||
@ -665,7 +665,7 @@ class FileMoveCopyOperation<T> : FileOperation<FileMoveCopyOperationData<T>, T>
|
||||
|
||||
filesMessageService.Send(file, toFolder, _headers, MessageAction.FileMovedWithOverwriting, file.Title, parentFolder.Title, toFolder.Title);
|
||||
|
||||
socketManager.DeleteFile(file);
|
||||
await socketManager.DeleteFile(file);
|
||||
|
||||
if (ProcessedFile(fileId))
|
||||
{
|
||||
|
@ -55,7 +55,8 @@ public class FileMarkerHelper<T>
|
||||
{
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var fileMarker = scope.ServiceProvider.GetService<FileMarker>();
|
||||
await fileMarker.ExecMarkFileAsNewAsync(obj);
|
||||
var socketManager = scope.ServiceProvider.GetService<SocketManager>();
|
||||
await fileMarker.ExecMarkFileAsNewAsync(obj, socketManager);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -76,7 +77,6 @@ public class FileMarker
|
||||
private readonly IDaoFactory _daoFactory;
|
||||
private readonly GlobalFolder _globalFolder;
|
||||
private readonly FileSecurity _fileSecurity;
|
||||
private readonly CoreBaseSettings _coreBaseSettings;
|
||||
private readonly AuthContext _authContext;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly FilesSettingsHelper _filesSettingsHelper;
|
||||
@ -87,7 +87,6 @@ public class FileMarker
|
||||
IDaoFactory daoFactory,
|
||||
GlobalFolder globalFolder,
|
||||
FileSecurity fileSecurity,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
AuthContext authContext,
|
||||
IServiceProvider serviceProvider,
|
||||
FilesSettingsHelper filesSettingsHelper,
|
||||
@ -98,14 +97,13 @@ public class FileMarker
|
||||
_daoFactory = daoFactory;
|
||||
_globalFolder = globalFolder;
|
||||
_fileSecurity = fileSecurity;
|
||||
_coreBaseSettings = coreBaseSettings;
|
||||
_authContext = authContext;
|
||||
_serviceProvider = serviceProvider;
|
||||
_filesSettingsHelper = filesSettingsHelper;
|
||||
this._cache = cache;
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
internal async Task ExecMarkFileAsNewAsync<T>(AsyncTaskData<T> obj)
|
||||
internal async Task ExecMarkFileAsNewAsync<T>(AsyncTaskData<T> obj, SocketManager socketManager)
|
||||
{
|
||||
_tenantManager.SetCurrentTenant(obj.TenantID);
|
||||
|
||||
@ -277,6 +275,7 @@ public class FileMarker
|
||||
else if (obj.FileEntry.RootFolderType == FolderType.VirtualRooms)
|
||||
{
|
||||
var virtualRoomsFolderId = await _globalFolder.GetFolderVirtualRoomsAsync(_daoFactory);
|
||||
userIDs.ForEach(userID => RemoveFromCahce(virtualRoomsFolderId, userID));
|
||||
|
||||
if (obj.FileEntry.ProviderEntry)
|
||||
{
|
||||
@ -355,7 +354,9 @@ public class FileMarker
|
||||
await GetNewTagsAsync(userID, entries.OfType<FileEntry<int>>().ToList());
|
||||
await GetNewTagsAsync(userID, entries.OfType<FileEntry<string>>().ToList());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (updateTags.Count > 0)
|
||||
{
|
||||
await tagDao.UpdateNewTags(updateTags, obj.CurrentAccountId);
|
||||
@ -366,6 +367,8 @@ public class FileMarker
|
||||
await tagDao.SaveTags(newTags, obj.CurrentAccountId);
|
||||
}
|
||||
|
||||
await Task.WhenAll(ExecMarkAsNewRequest(updateTags.Concat(newTags), socketManager));
|
||||
|
||||
async Task GetNewTagsAsync<T1>(Guid userID, List<FileEntry<T1>> entries)
|
||||
{
|
||||
var tagDao1 = _daoFactory.GetTagDao<T1>();
|
||||
@ -571,6 +574,16 @@ public class FileMarker
|
||||
await tagDao.RemoveTags(removeTags);
|
||||
}
|
||||
|
||||
var socketManager = _serviceProvider.GetRequiredService<SocketManager>();
|
||||
|
||||
var toRemove = removeTags.Select(r => new Tag(r.Name, r.Type, r.Owner, 0)
|
||||
{
|
||||
EntryId = r.EntryId,
|
||||
EntryType = r.EntryType
|
||||
});
|
||||
|
||||
await Task.WhenAll(ExecMarkAsNewRequest(updateTags.Concat(toRemove), socketManager));
|
||||
|
||||
async Task UpdateRemoveTags<TFolder>(Folder<TFolder> folder)
|
||||
{
|
||||
var tagDao = _daoFactory.GetTagDao<TFolder>();
|
||||
@ -813,6 +826,10 @@ public class FileMarker
|
||||
parentFolderTag = Tag.New(_authContext.CurrentAccount.ID, parent, 0);
|
||||
parentFolderTag.Id = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
((IFolder)parent).NewForMe = parentFolderTag.Count;
|
||||
}
|
||||
|
||||
if (parent.FolderType != FolderType.VirtualRooms && parent.RootFolderType == FolderType.VirtualRooms && parent.ProviderEntry)
|
||||
{
|
||||
@ -942,6 +959,21 @@ public class FileMarker
|
||||
var key = string.Format(CacheKeyFormat, userId, folderId);
|
||||
_cache.Remove(key);
|
||||
}
|
||||
|
||||
private IEnumerable<Task> ExecMarkAsNewRequest(IEnumerable<Tag> tags, SocketManager socketManager)
|
||||
{
|
||||
foreach (var t in tags)
|
||||
{
|
||||
if (t.EntryType == FileEntryType.File)
|
||||
{
|
||||
yield return socketManager.ExecMarkAsNewFile(t.EntryId, t.Count, t.Owner);
|
||||
}
|
||||
else if (t.EntryType == FileEntryType.Folder)
|
||||
{
|
||||
yield return socketManager.ExecMarkAsNewFolder(t.EntryId, t.Count, t.Owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Transient]
|
||||
|
@ -245,7 +245,7 @@ public class FileTrackerHelper
|
||||
if (await tracker.StartTrackAsync(fileId.ToString(), docKey))
|
||||
{
|
||||
_cache.Insert(Tracker + fileId, fileTracker, CacheTimeout, EvictionCallback(fileId, fileTracker));
|
||||
socketManager.StartEdit(fileId);
|
||||
await socketManager.StartEdit(fileId);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -26,34 +26,36 @@
|
||||
|
||||
namespace ASC.Web.Files.Utils;
|
||||
|
||||
[Scope]
|
||||
public class SocketManager
|
||||
public class SocketManager : SocketServiceClient
|
||||
{
|
||||
private readonly SocketServiceClient _socketServiceClient;
|
||||
private readonly FileDtoHelper _filesWrapperHelper;
|
||||
private readonly TenantManager _tenantManager;
|
||||
|
||||
public override string Hub => "files";
|
||||
|
||||
public SocketManager(
|
||||
IOptionsSnapshot<SocketServiceClient> optionsSnapshot,
|
||||
ILogger<SocketServiceClient> logger,
|
||||
IHttpClientFactory clientFactory,
|
||||
MachinePseudoKeys mashinePseudoKeys,
|
||||
IConfiguration configuration,
|
||||
FileDtoHelper filesWrapperHelper,
|
||||
TenantManager tenantManager
|
||||
)
|
||||
) : base(logger, clientFactory, mashinePseudoKeys, configuration)
|
||||
{
|
||||
_socketServiceClient = optionsSnapshot.Get("files");
|
||||
_filesWrapperHelper = filesWrapperHelper;
|
||||
_tenantManager = tenantManager;
|
||||
}
|
||||
|
||||
public void StartEdit<T>(T fileId)
|
||||
public async Task StartEdit<T>(T fileId)
|
||||
{
|
||||
var room = GetFileRoom(fileId);
|
||||
_socketServiceClient.StartEdit(fileId, room);
|
||||
await MakeRequest("start-edit", new { room, fileId });
|
||||
}
|
||||
|
||||
public void StopEdit<T>(T fileId)
|
||||
public async Task StopEdit<T>(T fileId)
|
||||
{
|
||||
var room = GetFileRoom(fileId);
|
||||
_socketServiceClient.StopEdit(fileId, room);
|
||||
await MakeRequest("stop-edit", new { room, fileId });
|
||||
}
|
||||
|
||||
public async Task CreateFileAsync<T>(File<T> file)
|
||||
@ -69,7 +71,7 @@ public class SocketManager
|
||||
serializerSettings.Converters.Add(new FileEntryWrapperConverter());
|
||||
var data = JsonSerializer.Serialize(await _filesWrapperHelper.GetAsync(file), serializerSettings);
|
||||
|
||||
_socketServiceClient.CreateFile(file.Id, room, data);
|
||||
await MakeRequest("create-file", new { room, fileId = file.Id, data });
|
||||
}
|
||||
|
||||
public async Task UpdateFileAsync<T>(File<T> file)
|
||||
@ -85,26 +87,40 @@ public class SocketManager
|
||||
serializerSettings.Converters.Add(new FileEntryWrapperConverter());
|
||||
var data = JsonSerializer.Serialize(await _filesWrapperHelper.GetAsync(file), serializerSettings);
|
||||
|
||||
_socketServiceClient.UpdateFile(file.Id, room, data);
|
||||
await MakeRequest("update-file", new { room, fileId = file.Id, data });
|
||||
}
|
||||
|
||||
public void DeleteFile<T>(File<T> file)
|
||||
public async Task DeleteFile<T>(File<T> file)
|
||||
{
|
||||
var room = GetFolderRoom(file.ParentId);
|
||||
_socketServiceClient.DeleteFile(file.Id, room);
|
||||
await MakeRequest("delete-file", new { room, fileId = file.Id });
|
||||
}
|
||||
|
||||
private string GetFileRoom<T>(T fileId)
|
||||
public async Task ExecMarkAsNewFile(object fileId, int count, Guid owner)
|
||||
{
|
||||
var tenantId = _tenantManager.GetCurrentTenant().Id;
|
||||
|
||||
return $"{tenantId}-FILE-{fileId}";
|
||||
var room = GetFileRoom(fileId, owner);
|
||||
await MakeRequest("markasnew-file", new { room, fileId, count });
|
||||
}
|
||||
|
||||
private string GetFolderRoom<T>(T folderId)
|
||||
public async Task ExecMarkAsNewFolder(object folderId, int count, Guid owner)
|
||||
{
|
||||
var room = GetFolderRoom(folderId, owner);
|
||||
await MakeRequest("markasnew-folder", new { room, folderId, count });
|
||||
}
|
||||
|
||||
private string GetFileRoom<T>(T fileId, Guid? owner = null)
|
||||
{
|
||||
var tenantId = _tenantManager.GetCurrentTenant().Id;
|
||||
var ownerData = owner.HasValue ? "-" + owner.Value : "";
|
||||
|
||||
return $"{tenantId}-DIR-{folderId}";
|
||||
return $"{tenantId}-FILE-{fileId}{ownerData}";
|
||||
}
|
||||
|
||||
private string GetFolderRoom<T>(T folderId, Guid? owner = null)
|
||||
{
|
||||
var tenantId = _tenantManager.GetCurrentTenant().Id;
|
||||
var ownerData = owner.HasValue ? "-" + owner.Value : "";
|
||||
|
||||
return $"{tenantId}-DIR-{folderId}{ownerData}";
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user