about summary refs log tree commit diff
path: root/configs/shared/emacs/.emacs.d/elpa/slack-20180712.2222/slack-message-buffer.el
diff options
context:
space:
mode:
Diffstat (limited to 'configs/shared/emacs/.emacs.d/elpa/slack-20180712.2222/slack-message-buffer.el')
-rw-r--r--configs/shared/emacs/.emacs.d/elpa/slack-20180712.2222/slack-message-buffer.el434
1 files changed, 434 insertions, 0 deletions
diff --git a/configs/shared/emacs/.emacs.d/elpa/slack-20180712.2222/slack-message-buffer.el b/configs/shared/emacs/.emacs.d/elpa/slack-20180712.2222/slack-message-buffer.el
new file mode 100644
index 000000000000..3b5d58c34fb0
--- /dev/null
+++ b/configs/shared/emacs/.emacs.d/elpa/slack-20180712.2222/slack-message-buffer.el
@@ -0,0 +1,434 @@
+;;; slack-message-buffer.el ---                      -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017
+
+;; Author:  <yuya373@yuya373>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'eieio)
+(require 'slack-room)
+(require 'slack-util)
+(require 'slack-room-buffer)
+(require 'slack-buffer)
+(require 'slack-request)
+
+(defface slack-new-message-marker-face
+  '((t (:foreground "#d33682"
+                    :weight bold
+                    :height 0.8)))
+  "Face used to New Message Marker."
+  :group 'slack)
+
+(define-derived-mode slack-message-buffer-mode slack-mode "Slack Message Buffer"
+  (add-hook 'lui-pre-output-hook 'slack-buffer-buttonize-link nil t)
+  (add-hook 'lui-pre-output-hook 'slack-add-face-lazy nil t)
+  (add-hook 'lui-pre-output-hook 'slack-search-code-block nil t)
+  (add-hook 'lui-post-output-hook 'slack-display-image t t)
+  ;; TODO move to `slack-room-buffer' ?
+  (cursor-sensor-mode)
+  (setq-local lui-max-buffer-size nil)
+  )
+
+(defclass slack-message-buffer (slack-room-buffer)
+  ((oldest :initform nil :type (or null string))
+   (latest :initform nil :type (or null string))
+   (marker-overlay :initform nil)
+   (update-mark-timer :initform '(nil . nil)) ;; (timestamp . timer)
+   ))
+
+(defmethod slack-buffer-last-read ((this slack-message-buffer))
+  (with-slots (room) this
+    (oref room last-read)))
+
+(cl-defmethod slack-buffer-update-mark ((this slack-message-buffer) &key (force nil))
+  (with-slots (room update-mark-timer) this
+    (let* ((ts (slack-get-ts))
+           (timer-timeout-sec (or (and force 0) 5))
+           (prev-mark (or (car update-mark-timer)
+                          (slack-buffer-last-read this)))
+           (prev-timer (cdr update-mark-timer)))
+      (when (or force (or (string< prev-mark ts)
+                          (string= prev-mark ts)))
+        (slack-log (format "%s: update mark to %s"
+                           (slack-room-name room)
+                           ts)
+                   (oref this team))
+        (when (timerp prev-timer)
+          (cancel-timer prev-timer))
+        (cl-labels
+            ((update-mark ()
+                          (slack-buffer-update-mark-request this ts)))
+          (setq update-mark-timer
+                (cons ts (run-at-time timer-timeout-sec nil #'update-mark))))))))
+
+(defmethod slack-buffer-update-mark-request ((this slack-message-buffer) ts &optional after-success)
+  (with-slots (room team) this
+    (when (slack-room-member-p room)
+      (cl-labels ((on-update-mark (&key data &allow-other-keys)
+                                  (slack-request-handle-error
+                                   (data "slack-buffer-update-mark-request")
+                                   (oset room last-read ts)
+                                   (slack-buffer-update-marker-overlay this)
+                                   (when (functionp after-success)
+                                     (funcall after-success)))))
+        (with-slots (id) room
+          (slack-request
+           (slack-request-create
+            (slack-room-update-mark-url room)
+            team
+            :type "POST"
+            :params (list (cons "channel"  id)
+                          (cons "ts"  ts))
+            :success #'on-update-mark)))))))
+
+(defmethod slack-buffer-send-message ((this slack-message-buffer) message)
+  (with-slots (room team) this
+    (slack-message-send-internal message (oref room id) team)))
+
+(defmethod slack-buffer-latest-ts ((this slack-message-buffer))
+  (with-slots (room) this
+    (slack-if-let* ((latest (oref room latest)))
+        (oref latest ts))))
+
+(defmethod slack-buffer-buffer ((this slack-message-buffer))
+  (let ((buffer-already-exists-p (get-buffer (slack-buffer-name this)))
+        (buffer (call-next-method))
+        (last-read (slack-buffer-last-read this)))
+    (with-current-buffer buffer
+      (if (slack-team-mark-as-read-immediatelyp (oref this team))
+          (progn
+            (unless buffer-already-exists-p
+              (goto-char (marker-position lui-input-marker)))
+            (and (slack-buffer-latest-ts this)
+                 (slack-buffer-update-mark-request this
+                                                   (slack-buffer-latest-ts this))))
+        (unless (string= "0" last-read)
+          (unless buffer-already-exists-p
+            (slack-buffer-goto last-read))
+          (slack-buffer-update-marker-overlay this))))
+
+    buffer))
+
+(defmethod slack-buffer-display-unread-threads ((this slack-message-buffer))
+  (with-slots (room team) this
+    (let* ((threads (mapcar #'(lambda (m) (oref m thread))
+                            (cl-remove-if
+                             #'(lambda (m)
+                                 (or (not (slack-message-thread-parentp m))
+                                     (not (< 0 (oref (oref m thread) unread-count)))))
+                             (oref room messages))))
+           (alist (mapcar #'(lambda (thread)
+                              (cons (slack-thread-title thread team) thread))
+                          (cl-sort threads
+                                   #'string>
+                                   :key #'(lambda (thread) (oref thread thread-ts)))))
+           (selected (slack-select-from-list (alist "Select Thread: "))))
+      (slack-thread-show-messages selected room team))))
+
+(defmethod slack-buffer-start-thread ((this slack-message-buffer) ts)
+  (with-slots (room team) this
+    (let* ((message (slack-room-find-message room ts))
+           (buf (slack-create-thread-message-buffer room team ts)))
+      (when (slack-reply-broadcast-message-p message)
+        (error "Can't start thread from broadcasted message"))
+      (when (slack-file-comment-message-p message)
+        (error "Can't start thread from file comment message"))
+      (when (slack-file-share-message-p message)
+        (error "Can't start thread from file share message"))
+      (slack-buffer-display buf))))
+
+(defmethod slack-buffer-major-mode ((this slack-message-buffer))
+  'slack-message-buffer-mode)
+
+(defmethod slack-buffer-init-buffer ((this slack-message-buffer))
+  (let ((buf (call-next-method)))
+    (with-current-buffer buf
+      (funcall (slack-buffer-major-mode this))
+      (slack-buffer-set-current-buffer this)
+      (goto-char (point-min))
+
+      (slack-buffer-insert-load-more this)
+
+      (with-slots (room team latest) this
+        (let* ((messages (slack-room-sorted-messages room))
+               (latest-message (car (last messages)))
+               (oldest-message (car messages)))
+          (cl-loop for m in messages
+                   do (if (and (or (null latest)
+                                   (string< latest (oref m ts)))
+                               (not (slack-thread-message-p m)))
+                          (slack-buffer-insert this m t)))
+          (when latest-message
+            (slack-buffer-update-lastest this (oref latest-message ts)))
+          (when oldest-message
+            (slack-buffer-update-oldest this oldest-message))))
+      )
+    (with-slots (room team) this
+      (let* ((class (eieio-object-class-name this)))
+        (slack-buffer-push-new-3 class room team)))
+    buf))
+
+
+(cl-defmethod slack-buffer-update ((this slack-message-buffer) message &key replace)
+  (with-slots (room team) this
+    (let ((buffer (get-buffer (slack-buffer-name this))))
+      (when (and (slack-team-mark-as-read-immediatelyp team)
+                 (slack-buffer-in-current-frame buffer))
+        (slack-buffer-update-mark-request this (oref message ts)))
+
+      (if replace (slack-buffer-replace this message)
+        (slack-buffer-update-lastest this (oref message ts))
+        (with-current-buffer buffer
+          (slack-buffer-insert this message))))))
+
+(defmethod slack-buffer-display-message-compose-buffer ((this slack-message-buffer))
+  (with-slots (room team) this
+    (let ((buf (slack-create-room-message-compose-buffer room team)))
+      (slack-buffer-display buf))))
+
+(defmethod slack-buffer-update-lastest ((this slack-message-buffer) latest)
+  (with-slots ((prev-latest latest)) this
+    (if (or (null prev-latest)
+            (string< prev-latest latest))
+        (setq prev-latest latest))))
+
+(defmethod slack-buffer-display-thread ((this slack-message-buffer) ts)
+  (with-slots (room team) this
+    (let ((thread (slack-room-find-thread room ts)))
+      (if thread (slack-thread-show-messages thread room team)
+        (slack-thread-start)))))
+
+(defmethod slack-buffer-display-edit-message-buffer ((this slack-message-buffer) ts)
+  (with-slots (room team) this
+    (let ((buf (slack-create-edit-message-buffer room team ts)))
+      (slack-buffer-display buf))))
+
+(defmethod slack-create-message-buffer ((room slack-room) team)
+  (slack-if-let* ((buffer (slack-buffer-find 'slack-message-buffer
+                                             room
+                                             team)))
+      buffer
+    (slack-message-buffer :room room :team team)))
+
+
+(defmethod slack-buffer-share-message ((this slack-message-buffer) ts)
+  (with-slots (room team) this
+    (let ((buf (slack-create-message-share-buffer room team ts)))
+      (slack-buffer-display buf))))
+
+(defmethod slack-buffer-add-reaction-to-message
+  ((this slack-message-buffer) reaction ts)
+  (with-slots (room team) this
+    (slack-message-reaction-add reaction ts room team)))
+
+(defmethod slack-buffer-add-reaction-to-file-comment
+  ((this slack-message-buffer) reaction id)
+  (with-slots (team) this
+    (slack-file-comment-add-reaction id reaction team)))
+
+(defmethod slack-buffer-remove-reaction-from-message
+  ((this slack-message-buffer) ts &optional file-comment-id)
+  (with-slots (room team) this
+    (let* ((message (slack-room-find-message room ts))
+           ;; TODO
+           (reactions (if file-comment-id
+                          (slack-message-reactions
+                           (oref (oref message file) initial-comment))
+                        (slack-message-reactions message)))
+           (reaction (slack-message-reaction-select reactions)))
+      (slack-message-reaction-remove reaction ts room team))))
+
+(defmethod slack-buffer-pins-remove ((this slack-message-buffer) ts)
+  (with-slots (room team) this
+    (slack-message-pins-request slack-message-pins-remove-url
+                                room team ts)))
+
+(defmethod slack-buffer-pins-add ((this slack-message-buffer) ts)
+  (with-slots (room team) this
+    (slack-message-pins-request slack-message-pins-add-url
+                                room team ts)))
+(defmethod slack-buffer-remove-star ((this slack-message-buffer) ts)
+  (with-slots (room team) this
+    (slack-if-let* ((message (slack-room-find-message room ts)))
+        (slack-message-star-api-request slack-message-stars-remove-url
+                                        (list (cons "channel" (oref room id))
+                                              (slack-message-star-api-params message))
+                                        team))))
+
+(defmethod slack-buffer-add-star ((this slack-message-buffer) ts)
+  (with-slots (room team) this
+    (slack-if-let* ((message (slack-room-find-message room ts)))
+        (slack-message-star-api-request slack-message-stars-add-url
+                                        (list (cons "channel" (oref room id))
+                                              (slack-message-star-api-params message))
+                                        team))))
+
+(defmethod slack-buffer-update-oldest ((this slack-message-buffer) message)
+  (when (and message (or (null (oref this oldest))
+                         (string< (oref message ts) (oref this oldest))))
+    (oset this oldest (oref message ts))))
+
+(defmethod slack-buffer-load-missing-messages ((this slack-message-buffer))
+  (with-slots (room team) this
+    (cl-labels
+        ((request-messages (latest)
+                           (slack-room-history-request room team
+                                                       :latest latest
+                                                       :count 100
+                                                       :after-success #'after-success))
+         (after-success (has-more)
+                        (let* ((messages (slack-room-sorted-messages room))
+                               (oldest-message (car messages))
+                               (latest-message (car (last messages))))
+                          (if has-more
+                              (request-messages (oref latest-message ts))
+                            (progn
+                              (with-current-buffer (slack-buffer-buffer this)
+                                (let ((inhibit-read-only t))
+                                  (slack-buffer-delete-overlay this)
+                                  (delete-region (point-min)
+                                                 (marker-position lui-output-marker)))
+                                (slack-buffer-prepare-marker-for-history this)
+                                (slack-buffer-insert-load-more this)
+                                (cl-loop for m in messages
+                                         do (slack-buffer-insert this m t))
+                                (slack-buffer-goto (slack-buffer-last-read this))
+                                (slack-buffer-update-marker-overlay this))
+                              (when oldest-message
+                                (slack-buffer-update-oldest this
+                                                            oldest-message)))))))
+      (oset room messages nil)
+      (request-messages nil))))
+
+(defmethod slack-buffer-load-more ((this slack-message-buffer))
+  (with-slots (room team oldest) this
+    (let ((current-ts (let ((change (next-single-property-change (point) 'ts)))
+                        (when change
+                          (get-text-property change 'ts))))
+          (cur-point (point)))
+      (cl-labels
+          ((update-buffer
+            (messages)
+            (with-current-buffer (slack-buffer-buffer this)
+              (slack-buffer-widen
+               (let ((inhibit-read-only t))
+                 (goto-char (point-min))
+
+                 (slack-if-let* ((loading-message-end
+                                  (slack-buffer-loading-message-end-point this)))
+                     (progn
+                       (slack-buffer-delete-overlay this)
+                       (delete-region (point-min) loading-message-end))
+                   (message "loading-message-end not found, oldest: %s" oldest))
+
+                 (set-marker lui-output-marker (point-min))
+                 (if (and messages (< 0 (length messages)))
+                     (slack-buffer-insert-load-more this)
+                   (let ((lui-time-stamp-position nil))
+                     (lui-insert "(no more messages)\n")))
+
+                 (cl-loop for m in messages
+                          do (slack-buffer-insert this m t))
+                 (lui-recover-output-marker)
+                 (slack-buffer-update-marker-overlay this)
+                 ))
+              (if current-ts
+                  (slack-buffer-goto current-ts)
+                (goto-char cur-point))))
+           (after-success (&rest _ignore)
+                          (let ((messages (cl-remove-if #'(lambda (e)
+                                                            (or (string< oldest e)
+                                                                (string= oldest e)))
+                                                        (slack-room-sorted-messages room)
+                                                        :key #'(lambda (e) (oref e ts)))))
+                            (update-buffer messages)
+                            (slack-buffer-update-oldest this (car messages)))))
+        (slack-room-history-request room team
+                                    :oldest oldest
+                                    :after-success #'after-success)))))
+
+(defmethod slack-buffer-display-pins-list ((this slack-message-buffer))
+  (with-slots (room team) this
+    (cl-labels
+        ((on-pins-list (&key data &allow-other-keys)
+                       (slack-request-handle-error
+                        (data "slack-room-pins-list")
+                        (let* ((buf (slack-create-pinned-items-buffer
+                                     room team (plist-get data :items))))
+                          (slack-buffer-display buf)))))
+      (slack-request
+       (slack-request-create
+        slack-room-pins-list-url
+        team
+        :params (list (cons "channel" (oref room id)))
+        :success #'on-pins-list)))))
+
+(defmethod slack-buffer-display-user-profile ((this slack-message-buffer))
+  (with-slots (room team) this
+    (let* ((members (cl-remove-if
+                     #'(lambda (e)
+                         (or (slack-user-self-p e team)
+                             (slack-user-hidden-p
+                              (slack-user--find e team))))
+                     (slack-room-get-members room)))
+           (user-alist (mapcar #'(lambda (u) (cons (slack-user-name u team) u))
+                               members))
+           (user-id (if (eq 1 (length members))
+                        (car members)
+                      (slack-select-from-list (user-alist "Select User: ")))))
+      (let ((buf (slack-create-user-profile-buffer team user-id)))
+        (slack-buffer-display buf)))))
+
+(defmethod slack-buffer-execute-slash-command ((this slack-message-buffer) command)
+  (with-slots (team) this
+    (slack-slash-commands-execute command team)))
+
+(defmethod slack-buffer-delete-overlay ((this slack-message-buffer))
+  (when (oref this marker-overlay)
+    (delete-overlay (oref this marker-overlay))))
+
+(defmethod slack-buffer-update-marker-overlay ((this slack-message-buffer))
+  (let ((buf (get-buffer (slack-buffer-name this))))
+    (and buf (with-current-buffer buf
+               (let* ((last-read (slack-buffer-last-read this))
+                      (beg (slack-buffer-ts-eq (point-min) (point-max) last-read))
+                      (end (and beg (next-single-property-change beg 'ts))))
+                 (when (and beg end)
+                   (if (oref this marker-overlay)
+                       (move-overlay (oref this marker-overlay)
+                                     beg end)
+                     (progn
+                       (oset this marker-overlay (make-overlay beg end))
+                       (let ((after-string
+                              (propertize "New Message"
+                                          'face
+                                          'slack-new-message-marker-face)))
+                         (overlay-put (oref this marker-overlay)
+                                      'after-string
+                                      (format "\n%s" after-string)))))))))))
+
+(defmethod slack-buffer-replace ((this slack-message-buffer) message)
+  (call-next-method)
+  (slack-buffer-update-marker-overlay this))
+
+(provide 'slack-message-buffer)
+;;; slack-message-buffer.el ends here