예제 #1
0
        public static void DrawChat(Graphics g, Dialog chat, Font fnt, ControlState state, int y = 0, int width = 200)
        {
            Color bg = Color.FromArgb(164, Color.White);

            if (state == ControlState.Hover)
            {
                bg = Color.FromArgb(182, Color.White);
            }
            else if (state == ControlState.Pressed)
            {
                bg = Color.FromArgb(196, Color.White);
            }

            g.FillRectangle(new SolidBrush(bg), 0, y, width, 50);

            if (chat == null)
            {
                return;
            }

            Message msg = chat.Message;

            if (msg == null)
            {
                return;
            }

            User usr = msg.User;

            if (usr != null)
            {
                Bitmap p = msg.GetPhoto();

                if (p == null)
                {
                    p = usr.GetPhoto();
                }

                if (p != null)
                {
                    g.DrawImage(p, new Rectangle(1, y + 1, 48, 48));
                }
            }

            DrawString(g, chat.Title, fnt, Brushes.Black, new Rectangle(55, y, width - 55, 50), StringAlignment.Near);

            if (state == ControlState.Active)
            {
                g.FillPolygon(new SolidBrush(Color.FromArgb(78, Color.White)), new []
                {
                    new Point(width, y),
                    new Point(width, y + 50),
                    new Point(width - 25, y + 25)
                });
            }
        }
예제 #2
0
        public void SendMessage(String text, bool encrypt = false)
        {
            if (this._chat == null)
            {
                return;
            }

            new Thread(async() =>
            {
                while (this._sending)
                {
                    Thread.Sleep(10);
                }

                String chat = "user_id=" + this._chat.Message.UserID;
                if (this._chat.Message.ChatID > 0)
                {
                    chat = "chat_id=" + this._chat.Message.ChatID;
                }

                if (!String.IsNullOrEmpty(text))
                {
                    this._sending = true;

                    this.InvokeEx(t => t.Invalidate());

                    if (encrypt)
                    {
                        if (String.IsNullOrEmpty(this._chat.CryptKey))
                        {
                            this.InvokeEx(t =>
                            {
                                DecryptMessagesForm frm = new DecryptMessagesForm();
                                if (frm.ShowDialog(t.FindForm()) == DialogResult.OK)
                                {
                                    t._chat.CryptKey = frm.Passphrase;
                                }
                            });
                        }

                        if (!String.IsNullOrEmpty(this._chat.CryptKey))
                        {
                            text = Message.Encrypt(text, this._chat.CryptKey);
                        }
                    }

                    await Message.Send(chat, text);

                    this._sending = false;

                    this.InvokeEx(t => t.Invalidate());
                }
            }).Start();
        }
예제 #3
0
        public ChatControl() : base()
        {
            AppEvents.On(AppEventType.OpenChat, OpenChat);

            LongPollServer.On(LPEventType.MessageAdded, async e =>
            {
                if (this._chat == null)
                {
                    return;
                }

                int msgID = (int)((long)((JValue)e.Data[0]).Value);

                Message msg = await Message.Get(msgID);

                if (msg.UserID == this._chat.Message.UserID || (msg.ChatID != 0 && msg.ChatID == this._chat.Message.ChatID))
                {
                    (new Thread(() =>
                    {
                        if (msg.Attachments != null && msg.Attachments.Length > 0)
                        {
                            foreach (Attachment a in msg.Attachments)
                            {
                                if (a.Type == "photo" && a.Photo != null)
                                {
                                    a.Photo.Load();
                                }
                            }
                        }

                        if (msg.CryptedNow && this._chat.CryptKey != null)
                        {
                            msg.Decrypt(this._chat.CryptKey);
                        }

                        msg.Author.GetPhoto();

                        this._messages.Add(msg);

                        this._loaded = true;

                        this._heightCalculated = false;

                        this.InvokeEx(t =>
                        {
                            t.Invalidate();
                        });
                    })).Start();
                }
            });
        }
예제 #4
0
        private void LoadChats()
        {
            (new Thread(async() =>
            {
                if (API.API.Session == null)
                {
                    return;
                }

                this.chats = await Dialog.GetDialogs();
                this.loaded = true;

                List <int> ids = new List <int>();
                foreach (Dialog chat in this.chats)
                {
                    Message msg = chat.Message;

                    if (!ids.Contains(msg.UserID))
                    {
                        ids.Add(msg.UserID);
                    }
                }

                User[] users = await User.GetAll(ids);

                foreach (User u in users)
                {
                    u.GetPhoto();
                }

                this.InvokeEx(t =>
                {
                    if (t != null && t.chats != null)
                    {
                        t.ContentHeight = t.chats.Count * 50;
                        t.Invalidate();
                    }
                });
            })).Start();
        }
예제 #5
0
        public static int DrawMessage(Graphics g, Message msg, Message prevMsg, Font fnt, ControlState state, int y = 0, int width = 500, int cHeight = 400, MouseState mouse = default(MouseState))
        {
            if (msg == null)
            {
                return(y);
            }

            int height = 0;

            const int padding = 10;

            const int avatarSz = 48;

            int hWidth   = width - avatarSz - 3 * padding;
            int msgWidth = width / 100 * 80;

            User usr = msg.Author;

            if (usr == null)
            {
                return(y);
            }

            Size hSize = Size.Empty;

            if (prevMsg == null || prevMsg.Author != usr)
            {
                int aX = padding;
                if (msg.Out)
                {
                    aX = width - padding - avatarSz;
                }

                Bitmap p = usr.GetPhoto();
                if (p != null && y > -avatarSz)
                {
                    g.DrawImage(p, new Rectangle(aX, y, avatarSz, avatarSz));
                }

                hSize = Size.Ceiling(g.MeasureString(usr.FullName, fnt, hWidth));

                int hX = 2 * padding + avatarSz;
                if (msg.Out)
                {
                    hX = width - 2 * padding - avatarSz - hSize.Width;
                }

                if (y > -hSize.Height)
                {
                    DrawString(g, usr.FullName, fnt, Brushes.DimGray, new Rectangle(new Point(hX, y), hSize));
                }
            }

            height += padding / 2 + hSize.Height;

            Size msgSize     = Size.Ceiling(g.MeasureString(msg.Body, fnt, msgWidth));
            Size msgRectSize = Size.Add(msgSize, new Size(2 * padding, 2 * padding));

            int rX = 2 * padding + avatarSz + 5;

            if (msg.Out)
            {
                rX = width - 2 * padding - avatarSz - msgRectSize.Width - 5;
            }

            int rY = y + padding / 2 + hSize.Height;

            if (msg.Attachments != null && msg.Attachments.Length > 0)
            {
                int ax = 0, ay = 0;
                int mw = 0, mh = 0;
                foreach (Attachment a in msg.Attachments)
                {
                    Size asz = a.Measure(g, fnt, msgWidth - ax, true);

                    if (mh < asz.Height)
                    {
                        mh = asz.Height;
                    }

                    if (ax + asz.Width > msgWidth)
                    {
                        ax  = 0;
                        ay += mh + padding;
                        mh  = 0;
                    }
                    else
                    {
                        ax += asz.Width + padding;
                    }

                    if (mw < ax)
                    {
                        mw = ax;
                    }
                }

                msgRectSize = new Size(Math.Max(msgSize.Width, mw) + padding, msgSize.Height + ay + mh + 2 * padding);

                rX = 2 * padding + avatarSz + 5;
                if (msg.Out)
                {
                    rX = width - 2 * padding - avatarSz - msgRectSize.Width - 5;
                }

                rY = y + padding / 2 + hSize.Height;
            }

            Color msgRectColor = Color.White;

            if (msg.Crypted)
            {
                msgRectColor = Color.Lime;
            }

            if (!msg.Read)
            {
                msgRectColor = Color.DodgerBlue;

                if (msg.Crypted)
                {
                    msgRectColor = Color.LimeGreen;
                }
            }

            Brush msgRectBrush = new SolidBrush(Color.FromArgb(128, msgRectColor));

            if (rY > -msgRectSize.Height && rY < cHeight)
            {
                g.FillRoundRectangle(msgRectBrush, new Rectangle(new Point(rX, rY), msgRectSize), padding / 2);
            }

            int tX = rX;
            int tY = rY + padding;

            if (msg.Out)
            {
                tX = rX + msgRectSize.Width;
            }

            g.FillPolygon(msgRectBrush, new[]
            {
                new Point(tX, tY),
                new Point(tX, tY + 16),
                new Point(((msg.Out) ? tX + 10 : tX - 10), tY + 8)
            });

            if (y + padding + padding / 2 + hSize.Height > -msgSize.Height && y < cHeight)
            {
                Rectangle msgRectangle = new Rectangle(new Point(rX + padding, y + padding + padding / 2 + hSize.Height), msgSize);

                /*if (msg.Body.Length > 256)
                 * {
                 *  DrawString(g, msg.Body, fnt, Brushes.Black, msgRectangle, StringAlignment.Near);
                 * }
                 * else
                 * {*/
                List <TextBlock> blocks;

                if (msg.RuntimeData.ContainsKey("TextBlocks"))
                {
                    blocks = (List <TextBlock>)msg.RuntimeData["TextBlocks"];
                }
                else
                {
                    blocks = new List <TextBlock>();

                    int blkend = 0;

                    MatchCollection matches = _URL.Matches(msg.Body);
                    if (matches.Count > 0)
                    {
                        foreach (Match m in matches)
                        {
                            String url = m.ToString();

                            int idx = msg.Body.IndexOf(url, StringComparison.Ordinal);

                            if (idx > blkend)
                            {
                                blocks.Add(new TextBlock(msg.Body, blkend, idx - blkend));
                            }

                            TextBlock blk = new TextBlock(msg.Body, idx, url.Length, TextStyle.Link);
                            blocks.Add(blk);

                            blkend = blk.End;
                        }
                    }

                    if (msg.Body.Length > blkend)
                    {
                        blocks.Add(new TextBlock(msg.Body, blkend, msg.Body.Length - blkend));
                    }

                    if (Emoji.FindEmojis(msg.Body).Count > 0)
                    {
                        List <TextBlock> nbl = new List <TextBlock>();

                        foreach (TextBlock b in blocks)
                        {
                            foreach (String em in Emoji.FindEmojis(b.Fragment))
                            {
                                int idx = b.Fragment.IndexOf(em, StringComparison.Ordinal);

                                if (idx > 0)
                                {
                                    nbl.Add(new TextBlock(msg.Body, b.Start, idx, b.Style, b.State));
                                }

                                nbl.Add(new EmojiBlock(msg.Body, b.Start + idx, em.Length, b.State));

                                if (idx + em.Length < b.Length)
                                {
                                    nbl.Add(new TextBlock(msg.Body, b.Start + idx + em.Length, b.Length - idx - em.Length, b.Style, b.State));
                                }
                            }
                        }

                        blocks = nbl;
                    }

                    Console.WriteLine(((msg.Body.Length > 32) ? msg.Body.Substring(0, 32) + "..." : msg.Body) + ": " + blocks.Count + " block(s)");

                    blocks.Sort((blk, blk2) => blk.Start.CompareTo(blk2.Start));

                    msg.RuntimeData.Add("TextBlocks", blocks);
                }

                if (blocks.Count > 16)
                {
                    DrawString(g, msg.Body, fnt, Brushes.Black, msgRectangle, StringAlignment.Near);
                }
                else
                {
                    int sX = rX + padding,
                        sY = y + padding + padding / 2 + hSize.Height,
                        eX = msgSize.Width,
                        eY = msgSize.Height;

                    int cX = 0, cY = 0, cH = 0;

                    CharacterRange[] ranges   = { new CharacterRange(0, 1) };
                    String           _c;
                    Rectangle        charRect = Rectangle.Empty;

                    int cP = 0;

                    using (StringFormat stringFormat = new StringFormat())
                    {
                        stringFormat.Alignment     = StringAlignment.Near;
                        stringFormat.LineAlignment = StringAlignment.Center;

                        foreach (TextBlock blk in blocks)
                        {
                            blk.StartPoint = new Point(cX, cY);

                            if (blk is EmojiBlock)
                            {
                                Bitmap e = ((EmojiBlock)blk).Emoji;

                                if (e != null)
                                {
                                    g.DrawImage(e, new Rectangle(new Point(sX + cX + 2, sY + cY), new Size(16, 16)));

                                    if (cH < 16)
                                    {
                                        cH = 16;
                                    }

                                    cX += 20;
                                    if (cX > eX)
                                    {
                                        cX  = 0;
                                        cY += cH;
                                    }
                                }

                                cP += blk.Length;
                            }
                            else
                            {
                                while (cP >= blk.Start && cP < blk.End)
                                {
                                    ranges[0].First = cP;

                                    stringFormat.SetMeasurableCharacterRanges(ranges);

                                    _c = msg.Body.Substring(cP, 1);

                                    charRect =
                                        Rectangle.Round(
                                            g.MeasureCharacterRanges(msg.Body, fnt, msgRectangle, stringFormat)[0]
                                            .GetBounds(g));

                                    if (cH < charRect.Height)
                                    {
                                        cH = charRect.Height;
                                    }

                                    Color c = Color.Black;
                                    if (blk.Style == TextStyle.Link)
                                    {
                                        c = Color.Blue;

                                        if (mouse != null)
                                        {
                                            int mpX = mouse.Position.X;
                                            int mpY = mouse.Position.Y;

                                            if (mpY >= sY + blk.StartPoint.Y && mpY <= sY + blk.EndPoint.Y &&
                                                mpX >= sX + blk.StartPoint.X &&
                                                mpX <= sX + blk.EndPoint.X)
                                            {
                                                blk.State = ControlState.Hover;

                                                if (mouse.Clicked)
                                                {
                                                    blk.State     = ControlState.Pressed;
                                                    mouse.Clicked = false;
                                                }
                                            }
                                            else
                                            {
                                                blk.State = ControlState.Idle;
                                            }

                                            if (blk.State != ControlState.Idle)
                                            {
                                                if (blk.State == ControlState.Hover)
                                                {
                                                    c = Color.DarkOrange;
                                                }

                                                if (blk.State == ControlState.Pressed)
                                                {
                                                    c = Color.Red;

                                                    App.Platform.OpenUrl(msg.Body.Substring(blk.Start, blk.Length));
                                                }

                                                g.FillRectangle(Brushes.White, charRect);
                                            }
                                        }
                                        else
                                        {
                                            blk.State = ControlState.Idle;
                                            c         = Color.Blue;
                                        }
                                    }

                                    g.DrawString(_c, fnt, new SolidBrush(c), sX + cX, sY + cY);

                                    if (blk.Style == TextStyle.Link)
                                    {
                                        g.DrawLine(new Pen(c), sX + cX + 2, sY + cY + cH, sX + cX + charRect.Width + 2,
                                                   sY + cY + cH);
                                    }

                                    cX += charRect.Width;
                                    if (cX > eX || _c == "\n")
                                    {
                                        cX  = 0;
                                        cY += cH;

                                        if (_c != "\n")
                                        {
                                            cH = 0;
                                        }
                                    }
                                    cP++;
                                }
                            }

                            blk.EndPoint = new Point(cX + charRect.Width + 2, cY + cH);
                        }
                    }
                }
            }

            height += msgRectSize.Height + padding;

            if (msg.Attachments != null && msg.Attachments.Length > 0)
            {
                int ax = 0, ay = 0;
                int mh = 0;
                foreach (Attachment a in msg.Attachments)
                {
                    Size asz = a.Measure(g, fnt, msgWidth - ax, true);

                    Rectangle aRect = new Rectangle(new Point(rX + padding + ax, rY + msgSize.Height + padding + ay), asz);

                    bool aHover = false, aClick = false;

                    if (mouse != null && aRect.Contains(mouse.Position))
                    {
                        aHover = true;

                        if (mouse.Clicked)
                        {
                            aClick        = true;
                            mouse.Clicked = false;
                        }
                    }

                    a.Draw(g, aRect, fnt, true, aHover, aClick);

                    if (mh < asz.Height)
                    {
                        mh = asz.Height;
                    }

                    if (ax + asz.Width > msgWidth)
                    {
                        ax  = 0;
                        ay += mh + padding;
                        mh  = 0;
                    }
                    else
                    {
                        ax += asz.Width + padding;
                    }
                }
            }

            return(height);
        }
예제 #6
0
        protected override void OnPaint(PaintEventArgs e)
        {
            this.OnPaintBackground(e);

            Graphics g = e.Graphics;

            g.SmoothingMode = SmoothingMode.HighQuality;

            g.FillRectangle(new SolidBrush(Color.FromArgb(196, Color.White)), this.ClientRectangle);

            if (!this._loaded || this._messages == null || this._messages.Count == 0)
            {
                Drawer.DrawString(g, "No messages", this.Font, Brushes.Black, this.ClientRectangle);
            }
            else
            {
                String bgi = this._chat.Message.Photo;

                if (String.IsNullOrEmpty(bgi))
                {
                    bgi = this._chat.Message.User.Photo;
                }

                if (!String.IsNullOrEmpty(bgi))
                {
                    Bitmap bg = Drawer.SetImageOpacity(bgi, 0.05f);
                    if (bg != null)
                    {
                        int sz = Math.Max(this.Width, this.Height);

                        g.DrawImage(bg, (this.Width - sz) / 2, (this.Height - sz) / 2, sz, sz);
                    }
                }

                int y = -this.ScrollOffset + 10;

                Message prevMsg = null;

                lock (_messages_lock)
                {
                    try
                    {
                        foreach (Message msg in this._messages)
                        {
                            y += Drawer.DrawMessage(g, msg, prevMsg, this.Font, ControlState.Idle, y, this.Width, this.Height, this.Mouse);

                            prevMsg = msg;
                        }
                    }
                    catch (Exception exception)
                    {
                        Console.WriteLine(exception);
                    }
                }

                if (!this._heightCalculated)
                {
                    this.ContentHeight = y + this.ScrollOffset;
                    this.ScrollOffset  = this.ContentHeight - this._oldH + this._so - ((this._oldH == 0) ? this.Height : 0);

                    this._heightCalculated = true;
                }
            }

            this.Mouse.Clicked = false;

            base.OnPaint(e);
        }