about summary refs log tree commit diff stats
path: root/browse-slack
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-10-09 12:35:13 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-10-09 12:35:13 -0700
commit78231d4c4b8eed429754274862eff0ea475e66ac (patch)
tree089f85a5102e8946457ed55118706cae9891b22f /browse-slack
parent23fe8b0ae9d448f8829e30db0ccda712f1abb930 (diff)
downloadmu-78231d4c4b8eed429754274862eff0ea475e66ac.tar.gz
slack: hide threads from the global view
To hide all comments from the same thread as the item at cursor, press
ctrl-h.

To later unhide everything, press ctrl-u.

Currently ctrl-u works by creating a whole new tab (that you can back
out of using Esc). That gives a way to undo it.

Still some rough edges:
  update number of items in view when hiding a thread
  avoid clipping menu in channel view
  undo a single hide without giving up previous ones
Diffstat (limited to 'browse-slack')
-rw-r--r--browse-slack/environment.mu154
1 files changed, 153 insertions, 1 deletions
diff --git a/browse-slack/environment.mu b/browse-slack/environment.mu
index 18162f7b..3d4b54db 100644
--- a/browse-slack/environment.mu
+++ b/browse-slack/environment.mu
@@ -18,6 +18,8 @@ type tab {
       # type 3: comments in a single thread
   item-index: int  # what item in the corresponding list we start rendering
                    # the current page at
+  # only for type 0
+  hidden-items: (handle stream int)
   # only for type 1
   channel-index: int
   # only for type 2
@@ -222,9 +224,16 @@ fn render-all-items screen: (addr screen), _current-tab: (addr tab), show-cursor
   var items-data/edi: (addr array item) <- copy _items-data
   var y/ecx: int <- copy 2/search-space-ver
   y <- add 1/item-padding-ver
-  {
+  $render-all-items:loop: {
     compare i, 0
     break-if-<
+    {
+      var hide?/eax: boolean <- should-hide? current-tab, i, _items
+      compare hide?, 0/false
+      break-if-=
+      i <- decrement
+      loop $render-all-items:loop
+    }
     compare y, screen-height
     break-if->=
     var offset/eax: (offset item) <- compute-offset items-data, i
@@ -423,6 +432,17 @@ fn render-main-menu screen: (addr screen), _env: (addr environment) {
   draw-text-rightward-from-cursor screen, " go to channels  ", width, 0xf/fg, 0/bg
   draw-text-rightward-from-cursor screen, " Enter ", width, 0/fg 0xf/bg
   draw-text-rightward-from-cursor screen, " go to thread  ", width, 0xf/fg, 0/bg
+  {
+    {
+      var is-all-items-or-channel?/eax: boolean <- current-tab-is-all-items-or-channel? _env
+      compare is-all-items-or-channel?, 0/false
+    }
+    break-if-=
+    draw-text-rightward-from-cursor screen, " ^h ", width, 0/fg 0xf/bg
+    draw-text-rightward-from-cursor screen, " hide thread  ", width, 0xf/fg, 0/bg
+    draw-text-rightward-from-cursor screen, " ^u ", width, 0/fg 0xf/bg
+    draw-text-rightward-from-cursor screen, " unhide all  ", width, 0xf/fg, 0/bg
+  }
   draw-text-rightward-from-cursor screen, " ^b ", width, 0/fg 0xf/bg
   draw-text-rightward-from-cursor screen, " << page  ", width, 0xf/fg, 0/bg
   draw-text-rightward-from-cursor screen, " ^f ", width, 0/fg 0xf/bg
@@ -879,6 +899,24 @@ fn update-main-panel env: (addr environment), key: byte, users: (addr array user
     return
   }
   {
+    compare key, 8/ctrl-h
+    break-if-!=
+    var is-all-items-or-channel?/eax: boolean <- current-tab-is-all-items-or-channel? env
+    compare is-all-items-or-channel?, 0/false
+    break-if-=
+    hide-thread env, users, channels, items
+    return
+  }
+  {
+    compare key, 0x15/ctrl-u
+    break-if-!=
+    var is-all-items-or-channel?/eax: boolean <- current-tab-is-all-items-or-channel? env
+    compare is-all-items-or-channel?, 0/false
+    break-if-=
+    new-all-items-tab env, users, channels, items
+    return
+  }
+  {
     compare key, 0x81/down-arrow
     break-if-!=
     next-item env, users, channels, items
@@ -904,6 +942,29 @@ fn update-main-panel env: (addr environment), key: byte, users: (addr array user
   }
 }
 
+fn current-tab-is-all-items-or-channel? _env: (addr environment) -> _/eax: boolean {
+  var env/esi: (addr environment) <- copy _env
+  var tabs-ah/eax: (addr handle array tab) <- get env, tabs
+  var _tabs/eax: (addr array tab) <- lookup *tabs-ah
+  var tabs/edx: (addr array tab) <- copy _tabs
+  var current-tab-index-a/eax: (addr int) <- get env, current-tab-index
+  var current-tab-index/eax: int <- copy *current-tab-index-a
+  var current-tab-offset/eax: (offset tab) <- compute-offset tabs, current-tab-index
+  var current-tab/edx: (addr tab) <- index tabs, current-tab-offset
+  var current-tab-type/eax: (addr int) <- get current-tab, type
+  {
+    compare *current-tab-type, 0/all-items
+    break-if-!=
+    return 1/true
+  }
+  {
+    compare *current-tab-type, 1/channel
+    break-if-!=
+    return 1/true
+  }
+  return 0/false
+}
+
 # TODO: clamp cursor within bounds
 fn update-channels-nav _env: (addr environment), key: byte, users: (addr array user), channels: (addr array channel), items: (addr item-list) {
   var env/edi: (addr environment) <- copy _env
@@ -955,6 +1016,30 @@ fn update-search _env: (addr environment), key: byte, users: (addr array user),
   edit-gap-buffer search-terms, g
 }
 
+fn new-all-items-tab _env: (addr environment), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
+  var env/edi: (addr environment) <- copy _env
+  var current-tab-index-addr/ecx: (addr int) <- get env, current-tab-index
+  increment *current-tab-index-addr
+  var tabs-ah/eax: (addr handle array tab) <- get env, tabs
+  var tabs/eax: (addr array tab) <- lookup *tabs-ah
+  var max-tabs/ebx: int <- length tabs
+  {
+    compare *current-tab-index-addr, max-tabs
+    break-if-<
+    abort "history overflow; grow max-history (we should probably improve this)"
+  }
+  var current-tab-index/ecx: int <- copy *current-tab-index-addr
+  var current-tab-offset/ecx: (offset tab) <- compute-offset tabs, current-tab-index
+  var current-tab/ecx: (addr tab) <- index tabs, current-tab-offset
+  clear-object current-tab
+  var items/eax: (addr item-list) <- copy _items
+  var items-data-first-free-a/eax: (addr int) <- get items, data-first-free
+  var final-item/edx: int <- copy *items-data-first-free-a
+  final-item <- decrement
+  var dest/edi: (addr int) <- get current-tab, item-index
+  copy-to *dest, final-item
+}
+
 fn new-thread-tab _env: (addr environment), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
   var env/edi: (addr environment) <- copy _env
   var current-tab-index-addr/ecx: (addr int) <- get env, current-tab-index
@@ -1025,6 +1110,72 @@ fn new-thread-tab _env: (addr environment), users: (addr array user), channels:
   abort "new-thread-tab: should never leave previous loop without returning"
 }
 
+# hide a thread in a (channel or all-items) tab
+fn hide-thread _env: (addr environment), users: (addr array user), channels: (addr array channel), items: (addr item-list) {
+  var env/edi: (addr environment) <- copy _env
+  var current-tab-index-addr/eax: (addr int) <- get env, current-tab-index
+  var current-tab-index/ecx: int <- copy *current-tab-index-addr
+  var tabs-ah/eax: (addr handle array tab) <- get env, tabs
+  var tabs/eax: (addr array tab) <- lookup *tabs-ah
+  var current-tab-offset/ecx: (offset tab) <- compute-offset tabs, current-tab-index
+  var current-tab/ecx: (addr tab) <- index tabs, current-tab-offset
+  var current-tab-hidden-items-ah/edx: (addr handle stream int) <- get current-tab, hidden-items
+  var current-tab-hidden-items/eax: (addr stream int) <- lookup *current-tab-hidden-items-ah
+  {
+    compare current-tab-hidden-items, 0
+    break-if-!=
+    populate-stream current-tab-hidden-items-ah, 0x10/max-hidden-threads
+    current-tab-hidden-items <- lookup *current-tab-hidden-items-ah
+  }
+  {
+    var too-many-hidden-items?/eax: boolean <- stream-full? current-tab-hidden-items
+    compare too-many-hidden-items?, 0/false
+    break-if-=
+    abort "too many hidden threads in this tab"  # TODO: create a space for flash error messages on screen
+    return
+  }
+  var current-item-index/esi: int <- item-index current-tab, channels
+  var current-post-index-value/ecx: int <- post-index items, current-item-index
+  # . turn current-post-index into an addr
+  var current-post-index-storage: int
+  copy-to current-post-index-storage, current-post-index-value
+  var current-post-index-addr/ecx: (addr int) <- address current-post-index-storage
+  #
+  write-to-stream current-tab-hidden-items, current-post-index-addr
+}
+
+fn should-hide? _tab: (addr tab), item-index: int, items: (addr item-list) -> _/eax: boolean {
+  var post-index/ecx: int <- post-index items, item-index
+  var tab/esi: (addr tab) <- copy _tab
+  var tab-hidden-items-ah/edx: (addr handle stream int) <- get tab, hidden-items
+  var tab-hidden-items/eax: (addr stream int) <- lookup *tab-hidden-items-ah
+  compare tab-hidden-items, 0
+  {
+    break-if-!=
+    return 0/false
+  }
+  rewind-stream tab-hidden-items
+  {
+    {
+      var done?/eax: boolean <- stream-empty? tab-hidden-items
+      compare done?, 0/false
+    }
+    break-if-!=
+    var curr-item: int
+    var curr-item-addr/edx: (addr int) <- address curr-item
+    read-from-stream tab-hidden-items, curr-item-addr
+    # if curr-item == post-index, return true
+    compare curr-item, post-index
+    {
+      break-if-!=
+      return 1/true
+    }
+    loop
+  }
+  return 0/false
+}
+
+# what index in the global items list is the cursor at in the current tab?
 fn item-index _tab: (addr tab), _channels: (addr array channel) -> _/esi: int {
   var tab/esi: (addr tab) <- copy _tab
   var tab-type/eax: (addr int) <- get tab, type
@@ -1063,6 +1214,7 @@ fn item-index _tab: (addr tab), _channels: (addr array channel) -> _/esi: int {
   return -1
 }
 
+# go from a comment item to its parent post
 fn post-index _items: (addr item-list), item-index: int -> _/ecx: int {
   var items/eax: (addr item-list) <- copy _items
   var items-data-ah/eax: (addr handle array item) <- get items, data