/* * Copyright (C) 2015 Actor LLC. <https://actor.im> */ package im.actor.core.viewmodel; import com.google.j2objc.annotations.ObjectiveCName; import com.google.j2objc.annotations.Property; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import im.actor.core.api.ApiMapValue; import im.actor.core.entity.Group; import im.actor.core.entity.GroupMember; import im.actor.core.entity.GroupType; import im.actor.core.viewmodel.generics.AvatarValueModel; import im.actor.core.viewmodel.generics.BooleanValueModel; import im.actor.core.viewmodel.generics.IntValueModel; import im.actor.core.viewmodel.generics.StringValueModel; import im.actor.runtime.annotations.MainThread; import im.actor.runtime.mvvm.BaseValueModel; import im.actor.runtime.mvvm.ModelChangedListener; import im.actor.runtime.mvvm.ValueModel; import im.actor.runtime.mvvm.ValueModelCreator; /** * Group View Model */ public class GroupVM extends BaseValueModel<Group> { public static ValueModelCreator<Group, GroupVM> CREATOR = GroupVM::new; @Property("nonatomic, readonly") private int groupId; @NotNull @Property("nonatomic, readonly") private GroupType groupType; @NotNull @Property("nonatomic, readonly") private StringValueModel name; @NotNull @Property("nonatomic, readonly") private AvatarValueModel avatar; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isMember; @NotNull @Property("nonatomic, readonly") private IntValueModel membersCount; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanWriteMessage; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanCall; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanClear; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanJoin; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanViewInfo; @NotNull @Property("nonatomic, readonly") private ValueModel<HashSet<GroupMember>> members; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isAsyncMembers; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanViewMembers; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanInviteMembers; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanEditInfo; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isHistoryShared; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanEditAdministration; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanEditAdmins; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanViewAdmins; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanLeave; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanDelete; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanInviteViaLink; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanKickInvited; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanKickAnyone; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanEditForeign; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isCanDeleteForeign; @NotNull @Property("nonatomic, readonly") private BooleanValueModel isDeleted; @NotNull @Property("nonatomic, readonly") private StringValueModel theme; @NotNull @Property("nonatomic, readonly") private StringValueModel about; @NotNull @Property("nonatomic, readonly") private StringValueModel shortName; @Property("nonatomic, readonly") private IntValueModel ownerId; @NotNull @Property("nonatomic, readonly") private ValueModel<Integer> presence; @NotNull @Property("nonatomic, readonly") private ValueModel<ApiMapValue> ext; @NotNull private ArrayList<ModelChangedListener<GroupVM>> listeners = new ArrayList<>(); /** * <p>INTERNAL API</p> * Create Group View Model * * @param rawObj initial value of Group */ public GroupVM(@NotNull Group rawObj) { super(rawObj); this.groupId = rawObj.getGroupId(); this.groupType = rawObj.getGroupType(); this.name = new StringValueModel("group." + groupId + ".title", rawObj.getTitle()); this.avatar = new AvatarValueModel("group." + groupId + ".avatar", rawObj.getAvatar()); this.isMember = new BooleanValueModel("group." + groupId + ".isMember", rawObj.isMember()); this.membersCount = new IntValueModel("group." + groupId + ".membersCount", rawObj.getMembersCount()); this.isCanWriteMessage = new BooleanValueModel("group." + groupId + ".can_write", rawObj.isCanSendMessage()); this.isCanCall = new BooleanValueModel("group." + groupId + ".can_call", rawObj.isCanCall()); this.isCanViewMembers = new BooleanValueModel("group." + groupId + ".can_view_members", rawObj.isCanViewMembers()); this.isCanInviteMembers = new BooleanValueModel("group." + groupId + ".can_invite_members", rawObj.isCanInviteMembers()); this.isCanEditInfo = new BooleanValueModel("group." + groupId + ".can_edit_info", rawObj.isCanEditInfo()); this.isAsyncMembers = new BooleanValueModel("group." + groupId + ".isAsyncMembers", rawObj.isAsyncMembers()); this.isCanEditAdministration = new BooleanValueModel("group." + groupId + ".isCanEditAdministration", rawObj.isCanEditAdministration()); this.isHistoryShared = new BooleanValueModel("group." + groupId + ".isHistoryShared", rawObj.isSharedHistory()); this.isCanEditAdmins = new BooleanValueModel("group." + groupId + ".isCanEditAdmins", rawObj.isCanEditAdmins()); this.isCanViewAdmins = new BooleanValueModel("group." + groupId + ".isCanViewAdmins", rawObj.isCanViewAdmins()); this.isCanLeave = new BooleanValueModel("group." + groupId + ".isCanLeave", rawObj.isCanLeave()); this.isCanDelete = new BooleanValueModel("group." + groupId + ".isCanDelete", rawObj.isCanDelete()); this.isCanInviteViaLink = new BooleanValueModel("group." + groupId + ".isCanInviteViaLink", rawObj.isCanInviteViaLink()); this.isCanKickInvited = new BooleanValueModel("group." + groupId + ".isCanKickInvited", rawObj.isCanKickInvited()); this.isCanKickAnyone = new BooleanValueModel("group." + groupId + ".isCanKickAnyone", rawObj.isCanKickAnyone()); this.isCanEditForeign = new BooleanValueModel("group." + groupId + ".isCanEditForeign", rawObj.isCanEditForeign()); this.isCanDeleteForeign = new BooleanValueModel("group." + groupId + ".isCanDeleteForeign", rawObj.isCanDeleteForeign()); this.isDeleted = new BooleanValueModel("group." + groupId + ".isDeleted", rawObj.isDeleted()); this.isCanClear = new BooleanValueModel("group." + groupId + ".isCanClear", rawObj.isCanClear()); this.isCanJoin = new BooleanValueModel("group." + groupId + ".isCanJoin", rawObj.isCanJoin()); this.isCanViewInfo = new BooleanValueModel("group." + groupId + ".isCanViewInfo", rawObj.isCanViewInfo()); this.ownerId = new IntValueModel("group." + groupId + ".membersCount", rawObj.getOwnerId()); this.members = new ValueModel<>("group." + groupId + ".members", new HashSet<>(rawObj.getMembers())); this.presence = new ValueModel<>("group." + groupId + ".presence", 0); this.theme = new StringValueModel("group." + groupId + ".theme", rawObj.getTopic()); this.about = new StringValueModel("group." + groupId + ".about", rawObj.getAbout()); this.shortName = new StringValueModel("group." + groupId + ".shortname", rawObj.getShortName()); this.ext = new ValueModel<>("group." + groupId + ".ext", rawObj.getExt()); } /** * Get Group Id * * @return Group Id */ @ObjectiveCName("getId") public int getId() { return groupId; } /** * Get Group Type * * @return Group Type */ @NotNull @ObjectiveCName("getGroupType") public GroupType getGroupType() { return groupType; } /** * Get Name Value Model * * @return Value Model of String */ @NotNull @ObjectiveCName("getNameModel") public StringValueModel getName() { return name; } /** * Get Avatar Value Model * * @return Value Model of Avatar */ @NotNull @ObjectiveCName("getAvatarModel") public AvatarValueModel getAvatar() { return avatar; } /** * Get About Value Model * * @return Value Model of String */ @NotNull @ObjectiveCName("getAboutModel") public StringValueModel getAbout() { return about; } /** * Get Theme Value Model * * @return Value Model of String */ @NotNull @ObjectiveCName("getThemeModel") public StringValueModel getTheme() { return theme; } /** * Get Short Name Model * * @return Value Model of String */ @NotNull @ObjectiveCName("getShortNameModel") public StringValueModel getShortName() { return shortName; } /** * Get membership Value Model * * @return Value Model of Boolean */ @NotNull @ObjectiveCName("isMemberModel") public BooleanValueModel isMember() { return isMember; } /** * Get Group members count * * @return members count */ @NotNull @ObjectiveCName("getMembersCountModel") public IntValueModel getMembersCount() { return membersCount; } /** * Can current user write message to a group * * @return can write message model */ @NotNull @ObjectiveCName("isCanWriteMessageModel") public BooleanValueModel getIsCanWriteMessage() { return isCanWriteMessage; } /** * Can current user view members of a group * * @return can view members model */ @NotNull @ObjectiveCName("getIsCanViewMembersModel") public BooleanValueModel getIsCanViewMembers() { return isCanViewMembers; } /** * Can current user edit group info * * @return can edit group info */ @NotNull @ObjectiveCName("isCanEditInfoModel") public BooleanValueModel getIsCanEditInfo() { return isCanEditInfo; } /** * Can current user invite members to a group * * @return can invite members model */ @NotNull @ObjectiveCName("getIsCanInviteMembersModel") public BooleanValueModel getIsCanInviteMembers() { return isCanInviteMembers; } /** * Is members should be fetched async * * @return is members async model */ @NotNull @ObjectiveCName("getIsAsyncMembersModel") public BooleanValueModel getIsAsyncMembers() { return isAsyncMembers; } /** * Is history shared in this group * * @return is history shared model */ @NotNull @ObjectiveCName("getIsHistorySharedModel") public BooleanValueModel getIsHistoryShared() { return isHistoryShared; } /** * Is current user can edit administration settings * * @return is can edit administration model */ @NotNull @ObjectiveCName("getIsCanEditAdministrationModel") public BooleanValueModel getIsCanEditAdministration() { return isCanEditAdministration; } /** * Is current user can leave group * * @return is current user can leave model */ @NotNull @ObjectiveCName("getIsCanLeaveModel") public BooleanValueModel getIsCanLeave() { return isCanLeave; } /** * Is current user can delete group * * @return is current user can delete model */ @NotNull @ObjectiveCName("getIsCanDeleteModel") public BooleanValueModel getIsCanDelete() { return isCanDelete; } /** * Is current user can call in this group * * @return is current user can call model */ @NotNull @ObjectiveCName("getIsCanCallModel") public BooleanValueModel getIsCanCall() { return isCanCall; } /** * Is current user can invite via link * * @return is current user can invite via link model */ @NotNull @ObjectiveCName("getIsCanInviteViaLinkModel") public BooleanValueModel getIsCanInviteViaLink() { return isCanInviteViaLink; } /** * Is current user can kick invited members * * @return is current user can kick invited model */ @NotNull @ObjectiveCName("getIsCanKickInvitedModel") public BooleanValueModel getIsCanKickInvited() { return isCanKickInvited; } /** * Is current user can kick anyone * * @return is current user can kick anyone model */ @NotNull @ObjectiveCName("getIsCanKickAnyoneModel") public BooleanValueModel getIsCanKickAnyone() { return isCanKickAnyone; } /** * Is current user can edit foreign messages * * @return is current user can edit foreign messages model */ @NotNull @ObjectiveCName("getIsCanEditForeignModel") public BooleanValueModel getIsCanEditForeign() { return isCanEditForeign; } /** * Is current user can delete foreign messages * * @return is current user can delete foreign messages model */ @NotNull @ObjectiveCName("getIsCanDeleteForeignModel") public BooleanValueModel getIsCanDeleteForeign() { return isCanDeleteForeign; } /** * Is current user can clear messages * * @return is current user can clear messages model */ @NotNull @ObjectiveCName("getIsCanClearModel") public BooleanValueModel getIsCanClear() { return isCanClear; } /** * Is current user can view info * * @return is current user can view info model */ @NotNull @ObjectiveCName("getIsCanViewInfoModel") public BooleanValueModel getIsCanViewInfo() { return isCanViewInfo; } /** * Is current user can join * * @return is current user can join model */ @NotNull public BooleanValueModel getIsCanJoin() { return isCanJoin; } /** * Is current user can edit admins * * @return is current user can edit admins */ @NotNull public BooleanValueModel getIsCanEditAdmins() { return isCanEditAdmins; } /** * Is group deleted * * @return is this group deleted model */ @NotNull @ObjectiveCName("getIsDeletedModel") public BooleanValueModel getIsDeleted() { return isDeleted; } /** * Get Group owner user id model * * @return creator owner id model */ @ObjectiveCName("getCreatorIdModel") public IntValueModel getOwnerId() { return ownerId; } /** * Get members Value Model * * @return Value Model of HashSet of GroupMember */ @NotNull @ObjectiveCName("getMembersModel") public ValueModel<HashSet<GroupMember>> getMembers() { return members; } /** * Get Online Value Model * * @return Value Model of Integer */ @NotNull @ObjectiveCName("getPresenceModel") public ValueModel<Integer> getPresence() { return presence; } /** * Get ext Value Model * * @return Value Model of ext */ @NotNull public ValueModel<ApiMapValue> getExt() { return ext; } /** * Subscribe for GroupVM updates * * @param listener Listener for updates */ @MainThread @ObjectiveCName("subscribeWithListener:") public synchronized void subscribe(@NotNull ModelChangedListener<GroupVM> listener) { if (listeners.contains(listener)) { return; } listeners.add(listener); listener.onChanged(this); } /** * Subscribe for GroupVM updates * * @param listener Listener for updates */ @MainThread @ObjectiveCName("subscribeWithListener:withNotify:") public synchronized void subscribe(@NotNull ModelChangedListener<GroupVM> listener, boolean notify) { if (listeners.contains(listener)) { return; } listeners.add(listener); if (notify) { listener.onChanged(this); } } /** * Unsubscribe from GroupVM updates * * @param listener Listener for updates */ @MainThread @ObjectiveCName("unsubscribeWithListener:") public synchronized void unsubscribe(@NotNull ModelChangedListener<GroupVM> listener) { listeners.remove(listener); } // // Update handling // @Override protected void updateValues(@NotNull Group rawObj) { boolean isChanged = name.change(rawObj.getTitle()); isChanged |= avatar.change(rawObj.getAvatar()); isChanged |= membersCount.change(rawObj.getMembersCount()); isChanged |= isMember.change(rawObj.isMember()); isChanged |= isCanWriteMessage.change(rawObj.isCanSendMessage()); isChanged |= theme.change(rawObj.getTopic()); isChanged |= about.change(rawObj.getAbout()); isChanged |= members.change(new HashSet<>(rawObj.getMembers())); isChanged |= ownerId.change(rawObj.getOwnerId()); isChanged |= isCanViewMembers.change(rawObj.isCanViewMembers()); isChanged |= isCanInviteMembers.change(rawObj.isCanInviteMembers()); isChanged |= isCanEditInfo.change(rawObj.isCanEditInfo()); isChanged |= shortName.change(rawObj.getShortName()); isChanged |= isAsyncMembers.change(rawObj.isAsyncMembers()); isChanged |= isHistoryShared.change(rawObj.isSharedHistory()); isChanged |= isCanEditAdministration.change(rawObj.isCanEditAdministration()); isChanged |= isCanEditAdmins.change(rawObj.isCanEditAdmins()); isChanged |= isCanViewAdmins.change(rawObj.isCanViewAdmins()); isChanged |= isCanLeave.change(rawObj.isCanLeave()); isChanged |= isCanDelete.change(rawObj.isCanDelete()); isChanged |= isCanInviteViaLink.change(rawObj.isCanInviteViaLink()); isChanged |= isCanKickInvited.change(rawObj.isCanKickInvited()); isChanged |= isCanKickAnyone.change(rawObj.isCanKickAnyone()); isChanged |= isCanEditForeign.change(rawObj.isCanEditForeign()); isChanged |= isCanDeleteForeign.change(rawObj.isCanDeleteForeign()); isChanged |= isDeleted.change(rawObj.isDeleted()); isChanged |= isCanClear.change(rawObj.isCanClear()); isChanged |= isCanViewInfo.change(rawObj.isCanViewInfo()); isChanged |= isCanJoin.change(rawObj.isCanJoin()); isChanged |= isCanCall.change(rawObj.isCanCall()); isChanged |= ext.change(rawObj.getExt()); if (isChanged) { notifyIfNeeded(); } } private synchronized void notifyIfNeeded() { if (listeners.size() > 0) { notifyChange(); } } private void notifyChange() { im.actor.runtime.Runtime.postToMainThread(() -> { for (ModelChangedListener<GroupVM> l : listeners) { l.onChanged(GroupVM.this); } }); } }