Skip to content
This repository has been archived by the owner on Feb 17, 2023. It is now read-only.

Commit

Permalink
Merge branch 'master' into web/calls
Browse files Browse the repository at this point in the history
  • Loading branch information
ex3ndr committed Feb 7, 2016
2 parents 4531be0 + 030b7fb commit 78c4ab1
Show file tree
Hide file tree
Showing 19 changed files with 842 additions and 140 deletions.
632 changes: 625 additions & 7 deletions actor-server/actor-core/src/main/actor-api/actor.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions actor-server/actor-core/src/main/protobuf/dialog.proto
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ message DialogCommands {
MessageReceived message_received = 4;
MessageRead message_read = 5;
Show show = 6;
Hide hide = 7;
Archive archive = 15;
Delete delete = 8;
SetReaction set_reaction = 9;
RemoveReaction remove_reaction = 10;
Expand Down Expand Up @@ -99,7 +99,7 @@ message DialogCommands {
required Peer dest = 1;
}

message Hide {
message Archive {
option (scalapb.message).extends = "im.actor.server.dialog.DialogCommand";

required Peer dest = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,31 @@ trait HistoryImplicits {
reactions: Seq[MessageReaction]
): Xor[String, ApiMessageContainer] = {
val in = CodedInputStream.newInstance(model.messageContentData)
Xor.fromEither(ApiMessage.parseFrom(in)) map { messageContent
val state = if (model.userId == model.senderUserId) {
if (model.date.getMillis <= lastReadAt.getMillis) {
Some(ApiMessageState.Read)
} else if (model.date.getMillis <= lastReceivedAt.getMillis) {
Some(ApiMessageState.Received)
try {
Xor.fromEither(ApiMessage.parseFrom(in)) map { messageContent
val state = if (model.userId == model.senderUserId) {
if (model.date.getMillis <= lastReadAt.getMillis) {
Some(ApiMessageState.Read)
} else if (model.date.getMillis <= lastReceivedAt.getMillis) {
Some(ApiMessageState.Received)
} else {
Some(ApiMessageState.Sent)
}
} else {
Some(ApiMessageState.Sent)
None // for incoming
}
} else {
None // for incoming
}

ApiMessageContainer(
senderUserId = model.senderUserId,
randomId = model.randomId,
date = model.date.getMillis,
message = messageContent,
state = state,
reactions = reactions.toVector map (r ApiMessageReaction(r.userIds.toVector, r.code))
)
ApiMessageContainer(
senderUserId = model.senderUserId,
randomId = model.randomId,
date = model.date.getMillis,
message = messageContent,
state = state,
reactions = reactions.toVector map (r ApiMessageReaction(r.userIds.toVector, r.code))
)
}
} catch {
case e: Exception Xor.Left(e.getMessage)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ trait DialogCommandHandlers extends UpdateCounters with PeersImplicits {
becomeStashing(replyTo ({
case seq: SeqStateDate
replyTo ! seq
if (state.isHidden) {
if (state.isArchived) {
self.tell(Show(peer), ActorRef.noSender)
}
updateMessageDate(state, seq.date)
Expand Down Expand Up @@ -80,7 +80,7 @@ trait DialogCommandHandlers extends UpdateCounters with PeersImplicits {
.map(_ SendMessageAck())
.pipeTo(sender()) onSuccess {
case _
if (state.isHidden) { self.tell(Show(peer), ActorRef.noSender) }
if (state.isArchived) { self.tell(Show(peer), ActorRef.noSender) }
}
}

Expand Down Expand Up @@ -172,37 +172,36 @@ trait DialogCommandHandlers extends UpdateCounters with PeersImplicits {
case Failure(e) log.error(e, "Failed to ack MessageRead")
}

protected def show(state: DialogState): Unit = {
if (!state.isHidden)
sender ! Status.Failure(DialogErrors.DialogAlreadyShown(peer))
protected def archive(state: DialogState): Unit = {
if (state.isArchived)
sender ! Status.Failure(DialogErrors.DialogAlreadyArchived(peer))
else {
val future =
(for {
_ db.run(DialogRepo.show(userId, peer))
seqstate userExt.notifyDialogsChanged(userId)
_ db.run(DialogRepo.archive(userId, peer))
_ db.run(markMessagesRead(selfPeer, peer, new DateTime))
_ userExt.notifyDialogsChanged(userId)
seqstate seqUpdExt.deliverSingleUpdate(userId, UpdateChatArchive(peer.asStruct))
} yield seqstate) pipeTo sender()

onSuccess(future) { _
updateShown(state)
updateArchived(state)
}
}
}

protected def hide(state: DialogState): Unit = {
if (state.isHidden)
sender ! Status.Failure(DialogErrors.DialogAlreadyHidden(peer))
protected def show(state: DialogState): Unit = {
if (!state.isArchived)
sender ! Status.Failure(DialogErrors.DialogAlreadyShown(peer))
else {
val future =
(for {
_ db.run(for {
_ DialogRepo.hide(userId, peer)
_ markMessagesRead(selfPeer, peer, new DateTime)
} yield ())
_ db.run(DialogRepo.show(userId, peer))
seqstate userExt.notifyDialogsChanged(userId)
} yield seqstate) pipeTo sender()

onSuccess(future) { _
updateHidden(state)
updateShown(state)
}
}
}
Expand Down Expand Up @@ -359,12 +358,12 @@ trait DialogCommandHandlers extends UpdateCounters with PeersImplicits {
private def updateReadDate(state: DialogState, date: Long): Unit =
context become initialized(state.updated(LastReadDate(date)))

private def updateArchived(state: DialogState): Unit =
context become initialized(state.updated(Archived))

private def updateShown(state: DialogState): Unit =
context become initialized(state.updated(Shown))

private def updateHidden(state: DialogState): Unit =
context become initialized(state.updated(Hidden))

private def updateFavourited(state: DialogState): Unit =
context become initialized(state.updated(Favourited))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ object DialogErrors {
object MessageToSelf extends DialogError("Private dialog with self is not allowed")

final case class DialogAlreadyShown(peer: Peer) extends DialogError(s"Dialog $peer is already shown")
final case class DialogAlreadyHidden(peer: Peer) extends DialogError(s"Dialog $peer is already hidden")
final case class DialogAlreadyFavourited(peer: Peer) extends DialogError(s"Dialog $peer is already favourited")
final case class DialogAlreadyUnfavourited(peer: Peer) extends DialogError(s"Dialog $peer is already unfavourited")
final case class DialogAlreadyArchived(peer: Peer) extends DialogError(s"Dialog $peer is already archived")

}
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,9 @@ final class DialogExtensionImpl(system: ActorSystem) extends DialogExtension wit
(userExt.processorRegion.ref ? Envelope(Peer.privat(userId)).withShow(Show(peer))).mapTo[SeqState]
}

def hide(userId: Int, peer: Peer): Future[SeqState] =
def archive(userId: Int, peer: Peer): Future[SeqState] =
withValidPeer(peer, userId, Future.failed[SeqState](DialogErrors.MessageToSelf)) {
(userExt.processorRegion.ref ? Envelope(Peer.privat(userId)).withHide(Hide(peer))).mapTo[SeqState]
(userExt.processorRegion.ref ? Envelope(Peer.privat(userId)).withArchive(Archive(peer))).mapTo[SeqState]
}

def favourite(userId: Int, peer: Peer): Future[SeqState] =
Expand Down Expand Up @@ -240,7 +240,7 @@ final class DialogExtensionImpl(system: ActorSystem) extends DialogExtension wit
def getGroupedDialogs(userId: Int) = {
db.run {
DialogRepo
.findNotArchivedSortByLastMessageData(userId, None, Int.MaxValue)
.fetchSortByLastMessageData(userId, None, Int.MaxValue)
.map(_ filterNot (dialogWithSelf(userId, _)))
.flatMap { dialogs
val (groupModels, privateModels, favouriteModels) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ object DialogEvents {
private[dialog] final case class LastReadDate(date: Long) extends DialogEvent

private[dialog] case object Shown extends DialogEvent
private[dialog] case object Hidden extends DialogEvent

private[dialog] case object Archived extends DialogEvent

private[dialog] case object Favourited extends DialogEvent
private[dialog] case object Unfavourited extends DialogEvent
Expand All @@ -46,37 +47,37 @@ private[dialog] object DialogState {
lastMessageDate: Long,
lastReceiveDate: Long,
lastReadDate: Long,
isHidden: Boolean,
isFavourite: Boolean,
isCreated: Boolean
) = DialogState(lastMessageDate, lastReceiveDate, lastReadDate, isHidden, isFavourite, isCreated)
isCreated: Boolean,
isArchived: Boolean
) = DialogState(lastMessageDate, lastReceiveDate, lastReadDate, isFavourite, isCreated, isArchived)

def fromModel(model: DialogModel, isCreated: Boolean): DialogState =
DialogState(
model.lastMessageDate.getMillis,
model.ownerLastReceivedAt.getMillis,
model.ownerLastReadAt.getMillis,
model.shownAt.isEmpty,
model.isFavourite,
isCreated = isCreated
isCreated = isCreated,
isArchived = model.archivedAt.isDefined
)
}

private[dialog] final case class DialogState(
lastMessageDate: Long, //we don't use it now anywhere. should we remove it?
lastReceiveDate: Long,
lastReadDate: Long,
isHidden: Boolean,
isFavourite: Boolean,
isCreated: Boolean
isCreated: Boolean,
isArchived: Boolean
) extends ProcessorState[DialogState, DialogEvent] {
import DialogEvents._
override def updated(e: DialogEvent): DialogState = e match {
case LastMessageDate(date) if date > this.lastMessageDate this.copy(lastMessageDate = date)
case LastReceiveDate(date) if date > this.lastReceiveDate this.copy(lastReceiveDate = date)
case LastReadDate(date) if date > this.lastReadDate this.copy(lastReadDate = date)
case Shown this.copy(isHidden = false)
case Hidden this.copy(isHidden = true)
case Shown this.copy(isArchived = false)
case Archived this.copy(isArchived = true)
case Favourited this.copy(isFavourite = true)
case Unfavourited this.copy(isFavourite = false)
case _ this
Expand Down Expand Up @@ -164,7 +165,7 @@ private[dialog] final class DialogProcessor(val userId: Int, val peer: Peer, ext
case sr: SetReaction if invokes(sr) setReaction(state, sr)
case rr: RemoveReaction if invokes(rr) removeReaction(state, rr)
case Show(_) show(state)
case Hide(_) hide(state)
case Archive(_) archive(state)
case Favourite(_) favourite(state)
case Unfavourite(_) unfavourite(state)
case Delete(_) delete(state)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,13 @@ private[sequence] class UpdatesConsumer(userId: Int, authId: Long, authSid: Int,
val updateFuture: Future[Update] =
presence match {
case Online
FastFuture.successful(UpdateUserOnline(p.userId))
FastFuture.successful(UpdateUserOnline(p.userId, None, None))
case Offline
lastSeenAt match {
case Some(date)
lastSeenOrOffline(p.userId, date.getMillis / 1000)
case None
FastFuture.successful(UpdateUserOffline(p.userId))
FastFuture.successful(UpdateUserOffline(p.userId, None, None))
}
}

Expand Down Expand Up @@ -209,18 +209,18 @@ private[sequence] class UpdatesConsumer(userId: Int, authId: Long, authSid: Int,
userCanLastSeen ParameterRepo.findValue(presenceUserId, Parameter.Keys.Privacy.LastSeen, Parameter.Values.Privacy.LastSeen.Always.value)
update if (selfCanLastSeen == Parameter.Values.Privacy.LastSeen.None.value ||
userCanLastSeen == Parameter.Values.Privacy.LastSeen.None.value) {
DBIO.successful(UpdateUserOffline(presenceUserId))
DBIO.successful(UpdateUserOffline(presenceUserId, None, None))
} else if (selfCanLastSeen == Parameter.Values.Privacy.LastSeen.Contacts.value ||
userCanLastSeen == Parameter.Values.Privacy.LastSeen.Contacts.value) {
for {
isInContacts UserContactRepo.exists(presenceUserId, userId)
} yield {
if (isInContacts)
UpdateUserLastSeen(presenceUserId, tsSeconds)
UpdateUserLastSeen(presenceUserId, tsSeconds, None, None)
else
UpdateUserOffline(presenceUserId)
UpdateUserOffline(presenceUserId, None, None)
}
} else DBIO.successful(UpdateUserLastSeen(presenceUserId, tsSeconds))
} else DBIO.successful(UpdateUserLastSeen(presenceUserId, tsSeconds, None, None))
} yield update
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ import org.joda.time.DateTime

object Dialog {
def apply(userId: Int, peer: Peer): Dialog =
Dialog(userId, peer, new DateTime(0), new DateTime(0), new DateTime(0), new DateTime(0), new DateTime(0), Some(new DateTime), false, false, new DateTime)
Dialog(userId, peer, new DateTime(0), new DateTime(0), new DateTime(0), new DateTime(0), new DateTime(0), Some(new DateTime), false, None, new DateTime)

def withLastMessageDate(userId: Int, peer: Peer, lastMessageDate: DateTime) =
Dialog(userId, peer, lastMessageDate, new DateTime(0), new DateTime(0), new DateTime(0), new DateTime(0), Some(new DateTime), false, false, new DateTime)
Dialog(userId, peer, lastMessageDate, new DateTime(0), new DateTime(0), new DateTime(0), new DateTime(0), Some(new DateTime), false, None, new DateTime)

def withLastReceivedAt(userId: Int, peer: Peer, lastReceivedAt: DateTime) =
Dialog(userId, peer, new DateTime(0), lastReceivedAt, new DateTime(0), new DateTime(0), new DateTime(0), Some(new DateTime), false, false, new DateTime)
Dialog(userId, peer, new DateTime(0), lastReceivedAt, new DateTime(0), new DateTime(0), new DateTime(0), Some(new DateTime), false, None, new DateTime)

def withOwnerLastReceivedAt(userId: Int, peer: Peer, ownerLastReceivedAt: DateTime) =
Dialog(userId, peer, new DateTime(0), new DateTime(0), new DateTime(0), ownerLastReceivedAt, new DateTime(0), Some(new DateTime), false, false, new DateTime)
Dialog(userId, peer, new DateTime(0), new DateTime(0), new DateTime(0), ownerLastReceivedAt, new DateTime(0), Some(new DateTime), false, None, new DateTime)

def withLastReadAt(userId: Int, peer: Peer, lastReadAt: DateTime) =
Dialog(userId, peer, new DateTime(0), new DateTime(0), lastReadAt, new DateTime(0), new DateTime(0), Some(new DateTime), false, false, new DateTime)
Dialog(userId, peer, new DateTime(0), new DateTime(0), lastReadAt, new DateTime(0), new DateTime(0), Some(new DateTime), false, None, new DateTime)

def withOwnerLastReadAt(userId: Int, peer: Peer, ownerLastReadAt: DateTime) =
Dialog(userId, peer, new DateTime(0), new DateTime(0), new DateTime(0), new DateTime(0), ownerLastReadAt, Some(new DateTime), false, false, new DateTime)
Dialog(userId, peer, new DateTime(0), new DateTime(0), new DateTime(0), new DateTime(0), ownerLastReadAt, Some(new DateTime), false, None, new DateTime)

def fromCommonAndUser(c: DialogCommon, u: UserDialog) = Dialog(
userId = u.userId,
Expand All @@ -31,7 +31,7 @@ object Dialog {
ownerLastReadAt = u.ownerLastReadAt,
shownAt = u.shownAt,
isFavourite = u.isFavourite,
isArchived = u.isArchived,
archivedAt = u.archivedAt,
createdAt = u.createdAt
)

Expand All @@ -47,7 +47,7 @@ case class Dialog(
ownerLastReadAt: DateTime,
shownAt: Option[DateTime],
isFavourite: Boolean,
isArchived: Boolean,
archivedAt: Option[DateTime],
createdAt: DateTime
)

Expand All @@ -66,5 +66,5 @@ case class UserDialog(
createdAt: DateTime,
shownAt: Option[DateTime],
isFavourite: Boolean,
isArchived: Boolean
archivedAt: Option[DateTime]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
ALTER TABLE user_dialogs ADD COLUMN archived_at TIMESTAMP DEFAULT NULL;
ALTER TABLE user_dialogs DROP COLUMN is_archived;
CREATE INDEX ON user_dialogs(user_id, archived_at);
UPDATE user_dialogs SET archived_at = (
CASE shown_at
WHEN NULL THEN NOW() + ((RANDOM()*1000)::INT::TEXT || ' seconds')::INTERVAL
ELSE NULL
END
);
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,15 @@ object UserContactRepo {
def byPK(ownerUserId: Int, contactUserId: Int) =
contacts.filter(c c.ownerUserId === ownerUserId && c.contactUserId === contactUserId)

def byOwnerUserIdNotDeleted(ownerUserId: Int) =
private def byOwnerUserIdNotDeleted(ownerUserId: Rep[Int]) =
contacts.filter(c c.ownerUserId === ownerUserId && c.isDeleted === false)

private val byOwnerUserIdNotDeletedC = Compiled(byOwnerUserIdNotDeleted _)

private val countC = Compiled { (userId: Rep[Int])
byOwnerUserIdNotDeleted(userId).length
}

def byPKNotDeleted(ownerUserId: Rep[Int], contactUserId: Rep[Int]) =
contacts.filter(c c.ownerUserId === ownerUserId && c.contactUserId === contactUserId && c.isDeleted === false)
val nameByPKNotDeletedC = Compiled(
Expand All @@ -53,8 +59,10 @@ object UserContactRepo {
def find(ownerUserId: Int, contactUserId: Int) =
byPKNotDeleted(ownerUserId, contactUserId).result.headOption

def count(ownerUserId: Int) = countC(ownerUserId).result

def findIds(ownerUserId: Int, contactUserIds: Set[Int]) =
byOwnerUserIdNotDeleted(ownerUserId).filter(_.contactUserId inSet contactUserIds).map(_.contactUserId).result
byOwnerUserIdNotDeletedC.applied(ownerUserId).filter(_.contactUserId inSet contactUserIds).map(_.contactUserId).result

def findOwners(contactUserId: Int) = byContactUserIdC(contactUserId).result

Expand Down
Loading

0 comments on commit 78c4ab1

Please sign in to comment.