/* * Copyright (C) 2015 Actor LLC. <https://actor.im> */ package im.actor.core.modules.typing; import java.util.HashMap; import java.util.HashSet; import im.actor.core.api.ApiTypingType; import im.actor.core.modules.ModuleContext; import im.actor.core.modules.ModuleActor; import im.actor.runtime.actors.ActorCreator; import im.actor.runtime.actors.ActorRef; import im.actor.runtime.actors.ActorSystem; import im.actor.runtime.actors.ActorCancellable; import im.actor.runtime.actors.Props; import im.actor.runtime.annotations.Verified; @Verified public class TypingActor extends ModuleActor { public static ActorRef get(final ModuleContext messenger) { return ActorSystem.system().actorOf("actor/typing", () -> new TypingActor(messenger)); } private static final int TYPING_TEXT_TIMEOUT = 7000; private HashMap<Integer, ActorCancellable> typingsCancellables = new HashMap<>(); private HashSet<Integer> typings = new HashSet<>(); private HashMap<Integer, HashSet<Integer>> groupTypings = new HashMap<>(); private HashMap<Integer, HashMap<Integer, ActorCancellable>> groupCancellables = new HashMap<>(); public TypingActor(ModuleContext messenger) { super(messenger); } @Verified private void privateTyping(int uid, ApiTypingType type) { // Support only text typings if (type != ApiTypingType.TEXT) { return; } if (getUser(uid) == null) { return; } if (!typings.contains(uid)) { typings.add(uid); context().getTypingModule().getTyping(uid).getTyping().change(true); } if (typingsCancellables.containsKey(uid)) { typingsCancellables.remove(uid).cancel(); } typingsCancellables.put(uid, schedule(new StopTyping(uid), TYPING_TEXT_TIMEOUT)); } @Verified private void stopPrivateTyping(int uid) { if (typings.contains(uid)) { typings.remove(uid); if (typingsCancellables.containsKey(uid)) { typingsCancellables.remove(uid).cancel(); } context().getTypingModule().getTyping(uid).getTyping().change(false); } } @Verified private void groupTyping(int gid, int uid, ApiTypingType type) { // Support only text typings if (type != ApiTypingType.TEXT) { return; } if (getGroup(gid) == null) { return; } if (getUser(uid) == null) { return; } if (!groupTypings.containsKey(gid)) { HashSet<Integer> set = new HashSet<Integer>(); set.add(uid); groupTypings.put(gid, set); context().getTypingModule() .getGroupTyping(gid) .getActive() .change(new int[]{uid}); } else { HashSet<Integer> src = groupTypings.get(gid); if (!src.contains(uid)) { src.add(uid); Integer[] ids = src.toArray(new Integer[src.size()]); int[] ids2 = new int[ids.length]; for (int i = 0; i < ids.length; i++) { ids2[i] = ids[i]; } context().getTypingModule() .getGroupTyping(gid) .getActive() .change(ids2); } } if (!groupCancellables.containsKey(gid)) { groupCancellables.put(gid, new HashMap<>()); } HashMap<Integer, ActorCancellable> cancellables = groupCancellables.get(gid); if (cancellables.containsKey(uid)) { cancellables.remove(uid).cancel(); } cancellables.put(uid, schedule(new StopGroupTyping(gid, uid), TYPING_TEXT_TIMEOUT)); } @Verified private void stopGroupTyping(int gid, int uid) { if (!groupTypings.containsKey(gid)) { return; } HashSet<Integer> set = groupTypings.get(gid); if (set.contains(uid)) { set.remove(uid); Integer[] ids = set.toArray(new Integer[set.size()]); int[] ids2 = new int[ids.length]; for (int i = 0; i < ids.length; i++) { ids2[i] = ids[i]; } context().getTypingModule() .getGroupTyping(gid) .getActive() .change(ids2); } } // Messages @Override public void onReceive(Object message) { if (message instanceof PrivateTyping) { PrivateTyping typing = (PrivateTyping) message; privateTyping(typing.getUid(), typing.getType()); } else if (message instanceof GroupTyping) { GroupTyping typing = (GroupTyping) message; groupTyping(typing.getGid(), typing.getUid(), typing.getType()); } else if (message instanceof StopTyping) { StopTyping typing = (StopTyping) message; stopPrivateTyping(typing.getUid()); } else if (message instanceof StopGroupTyping) { StopGroupTyping typing = (StopGroupTyping) message; stopGroupTyping(typing.getGid(), typing.getUid()); } else { super.onReceive(message); } } public static class StopTyping { private int uid; public StopTyping(int uid) { this.uid = uid; } public int getUid() { return uid; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; StopTyping that = (StopTyping) o; if (uid != that.uid) return false; return true; } @Override public int hashCode() { return uid; } } public static class StopGroupTyping { private int gid; private int uid; public StopGroupTyping(int gid, int uid) { this.gid = gid; this.uid = uid; } public int getGid() { return gid; } public int getUid() { return uid; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; StopGroupTyping that = (StopGroupTyping) o; if (gid != that.gid) return false; if (uid != that.uid) return false; return true; } @Override public int hashCode() { int result = gid; result = 31 * result + uid; return result; } } public static class PrivateTyping { private int uid; private ApiTypingType type; public PrivateTyping(int uid, ApiTypingType type) { this.uid = uid; this.type = type; } public int getUid() { return uid; } public ApiTypingType getType() { return type; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PrivateTyping that = (PrivateTyping) o; if (type != that.type) return false; if (uid != that.uid) return false; return true; } @Override public int hashCode() { int result = uid; result = 31 * result + type.getValue(); return result; } } public static class GroupTyping { private int gid; private int uid; private ApiTypingType type; public GroupTyping(int gid, int uid, ApiTypingType type) { this.gid = gid; this.uid = uid; this.type = type; } public int getGid() { return gid; } public int getUid() { return uid; } public ApiTypingType getType() { return type; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; GroupTyping that = (GroupTyping) o; if (gid != that.gid) return false; if (type != that.type) return false; if (uid != that.uid) return false; return true; } @Override public int hashCode() { int result = gid; result = 31 * result + uid; result = 31 * result + type.getValue(); return result; } } }