Add locks and other sync stuff
This commit is contained in:
parent
60e3fe3927
commit
bc7e2d9a1c
@ -21,7 +21,7 @@ precompiled executables. For now, you can either download
|
|||||||
a CI build from [dl.maunium.net/programs/gomuks](https://dl.maunium.net/programs/gomuks)
|
a CI build from [dl.maunium.net/programs/gomuks](https://dl.maunium.net/programs/gomuks)
|
||||||
or compile from source:
|
or compile from source:
|
||||||
|
|
||||||
0. Install [Go](https://golang.org/) 1.11 or higher
|
0. Install [Go](https://golang.org/) 1.12 or higher
|
||||||
1. Clone the repo: `git clone https://github.com/tulir/gomuks.git && cd gomuks`
|
1. Clone the repo: `git clone https://github.com/tulir/gomuks.git && cd gomuks`
|
||||||
2. Build: `go build`
|
2. Build: `go build`
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ func PrettyPanic(panic interface{}) {
|
|||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
fmt.Fprintln(&buf, panic)
|
fmt.Fprintln(&buf, panic)
|
||||||
buf.Write(debug.Stack())
|
buf.Write(debug.Stack())
|
||||||
err := ioutil.WriteFile(traceFile, buf.Bytes(), 0644)
|
err := ioutil.WriteFile(traceFile, buf.Bytes(), 0640)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Saving the stack trace to", traceFile, "failed:")
|
fmt.Println("Saving the stack trace to", traceFile, "failed:")
|
||||||
|
18
go.mod
18
go.mod
@ -4,22 +4,26 @@ go 1.12
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alecthomas/chroma v0.6.3
|
github.com/alecthomas/chroma v0.6.3
|
||||||
|
github.com/alecthomas/kong v0.1.16 // indirect
|
||||||
|
github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1 // indirect
|
||||||
github.com/disintegration/imaging v1.6.0
|
github.com/disintegration/imaging v1.6.0
|
||||||
github.com/kyokomi/emoji v2.1.0+incompatible
|
github.com/kyokomi/emoji v2.1.0+incompatible
|
||||||
github.com/lithammer/fuzzysearch v1.0.2
|
github.com/lithammer/fuzzysearch v1.0.2
|
||||||
github.com/lucasb-eyer/go-colorful v1.0.1
|
github.com/lucasb-eyer/go-colorful v1.0.2
|
||||||
|
github.com/mattn/go-colorable v0.1.1 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.7 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.4
|
github.com/mattn/go-runewidth v0.0.4
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.0.1
|
github.com/russross/blackfriday/v2 v2.0.1
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||||
|
github.com/stretchr/objx v0.2.0 // indirect
|
||||||
go.etcd.io/bbolt v1.3.2
|
go.etcd.io/bbolt v1.3.2
|
||||||
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5 // indirect
|
golang.org/x/image v0.0.0-20190424155947-59b11bec70c7
|
||||||
golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f
|
golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||||
golang.org/x/sys v0.0.0-20190410170021-cc4d4f50624c // indirect
|
|
||||||
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 // indirect
|
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.2.2
|
gopkg.in/yaml.v2 v2.2.2
|
||||||
maunium.net/go/mautrix v0.1.0-alpha.3.0.20190410194750-53c7c9d954c8
|
maunium.net/go/mautrix v0.1.0-alpha.3.0.20190410194750-53c7c9d954c8
|
||||||
maunium.net/go/mauview v0.0.0-20190406150001-ad4a4e562f9e
|
maunium.net/go/mauview v0.0.0-20190426104003-3e5387b8a125
|
||||||
maunium.net/go/tcell v0.0.0-20190406145848-d520315b0ddb
|
maunium.net/go/tcell v0.0.0-20190426103942-24a060c2189b
|
||||||
)
|
)
|
||||||
|
27
go.sum
27
go.sum
@ -1,11 +1,15 @@
|
|||||||
|
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
||||||
github.com/alecthomas/chroma v0.6.3 h1:8H1D0yddf0mvgvO4JDBKnzLd9ERmzzAijBxnZXGV/FA=
|
github.com/alecthomas/chroma v0.6.3 h1:8H1D0yddf0mvgvO4JDBKnzLd9ERmzzAijBxnZXGV/FA=
|
||||||
github.com/alecthomas/chroma v0.6.3/go.mod h1:quT2EpvJNqkuPi6DmBHB+E33FXBgBBPzyH5++Dn1LPc=
|
github.com/alecthomas/chroma v0.6.3/go.mod h1:quT2EpvJNqkuPi6DmBHB+E33FXBgBBPzyH5++Dn1LPc=
|
||||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
||||||
github.com/alecthomas/kong v0.1.15/go.mod h1:0m2VYms8rH0qbCqVB2gvGHk74bqLIq0HXjCs5bNbNQU=
|
github.com/alecthomas/kong v0.1.15/go.mod h1:0m2VYms8rH0qbCqVB2gvGHk74bqLIq0HXjCs5bNbNQU=
|
||||||
|
github.com/alecthomas/kong v0.1.16/go.mod h1:0m2VYms8rH0qbCqVB2gvGHk74bqLIq0HXjCs5bNbNQU=
|
||||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||||
|
github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
|
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
|
||||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
|
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/disintegration/imaging v1.6.0 h1:nVPXRUUQ36Z7MNf0O77UzgnOb1mkMMor7lmJMJXc/mA=
|
github.com/disintegration/imaging v1.6.0 h1:nVPXRUUQ36Z7MNf0O77UzgnOb1mkMMor7lmJMJXc/mA=
|
||||||
@ -20,8 +24,13 @@ github.com/lithammer/fuzzysearch v1.0.2 h1:AjCE2iwc5y+8K+h2nXVc0Pmrpjvu+JVqMgiZ0
|
|||||||
github.com/lithammer/fuzzysearch v1.0.2/go.mod h1:bvAJyokfCQ7Vknrd4Kgc+izmMrPj5CiBAu2t6rK1Kak=
|
github.com/lithammer/fuzzysearch v1.0.2/go.mod h1:bvAJyokfCQ7Vknrd4Kgc+izmMrPj5CiBAu2t6rK1Kak=
|
||||||
github.com/lucasb-eyer/go-colorful v1.0.1 h1:nKJRBvZWPzvkwB4sY8A3U4zgqLf2Y9c02yzPsbXu/5c=
|
github.com/lucasb-eyer/go-colorful v1.0.1 h1:nKJRBvZWPzvkwB4sY8A3U4zgqLf2Y9c02yzPsbXu/5c=
|
||||||
github.com/lucasb-eyer/go-colorful v1.0.1/go.mod h1:tLy1nWSoU0DGtxQyNRrUmb6PUiB7usbds6gd97XTXwA=
|
github.com/lucasb-eyer/go-colorful v1.0.1/go.mod h1:tLy1nWSoU0DGtxQyNRrUmb6PUiB7usbds6gd97XTXwA=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
|
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
|
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
|
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
|
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
|
||||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
||||||
@ -35,8 +44,11 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
|||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/zyedidia/clipboard v0.0.0-20180718195219-bd31d747117d h1:Lhqt2eo+rgM8aswvM7nTtAMVm8ARPWzkE9n6eZDOccY=
|
github.com/zyedidia/clipboard v0.0.0-20180718195219-bd31d747117d h1:Lhqt2eo+rgM8aswvM7nTtAMVm8ARPWzkE9n6eZDOccY=
|
||||||
github.com/zyedidia/clipboard v0.0.0-20180718195219-bd31d747117d/go.mod h1:WDk3p8GiZV9+xFWlSo8qreeoLhW6Ik692rqXk+cNeRY=
|
github.com/zyedidia/clipboard v0.0.0-20180718195219-bd31d747117d/go.mod h1:WDk3p8GiZV9+xFWlSo8qreeoLhW6Ik692rqXk+cNeRY=
|
||||||
go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk=
|
go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk=
|
||||||
@ -44,23 +56,38 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||||
|
golang.org/x/crypto v0.0.0-20190424203555-c05e17bb3b2d/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||||
golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f h1:FO4MZ3N56GnxbqxGKqh+YTzUWQ2sDwtFQEZgLOxh9Jc=
|
golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f h1:FO4MZ3N56GnxbqxGKqh+YTzUWQ2sDwtFQEZgLOxh9Jc=
|
||||||
golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
golang.org/x/image v0.0.0-20190424155947-59b11bec70c7 h1:OIchhgIITCxOyycwe8n9adxV37/WqbetxrpXNm7oPqI=
|
||||||
|
golang.org/x/image v0.0.0-20190424155947-59b11bec70c7/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/net v0.0.0-20190110200230-915654e7eabc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190110200230-915654e7eabc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190326090315-15845e8f865b/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190326090315-15845e8f865b/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6 h1:FP8hkuE6yUEaJnK7O2eTuejKWwW+Rhfj80dQ2JcKxCU=
|
||||||
|
golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190410170021-cc4d4f50624c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190410170021-cc4d4f50624c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190425145619-16072639606e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw=
|
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 h1:MZF6J7CV6s/h0HBkfqebrYfKCVEo5iN+wzE4QhV3Evo=
|
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 h1:MZF6J7CV6s/h0HBkfqebrYfKCVEo5iN+wzE4QhV3Evo=
|
||||||
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2/go.mod h1:s1Sn2yZos05Qfs7NKt867Xe18emOmtsO3eAKbDaon0o=
|
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2/go.mod h1:s1Sn2yZos05Qfs7NKt867Xe18emOmtsO3eAKbDaon0o=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
@ -178,8 +178,10 @@ func (c *Container) UpdatePushRules() {
|
|||||||
resp, err := pushrules.GetPushRules(c.client)
|
resp, err := pushrules.GetPushRules(c.client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debug.Print("Failed to fetch push rules:", err)
|
debug.Print("Failed to fetch push rules:", err)
|
||||||
}
|
c.config.PushRules = &pushrules.PushRuleset{}
|
||||||
|
} else {
|
||||||
c.config.PushRules = resp
|
c.config.PushRules = resp
|
||||||
|
}
|
||||||
c.config.SavePushRules()
|
c.config.SavePushRules()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ func (rs *PushRuleset) MarshalJSON() ([]byte, error) {
|
|||||||
|
|
||||||
// DefaultPushActions is the value returned if none of the rule
|
// DefaultPushActions is the value returned if none of the rule
|
||||||
// collections in a Ruleset match the event given to GetActions()
|
// collections in a Ruleset match the event given to GetActions()
|
||||||
var DefaultPushActions = make(PushActionArray, 0)
|
var DefaultPushActions = PushActionArray{&PushAction{Action: ActionDontNotify}}
|
||||||
|
|
||||||
// GetActions matches the given event against all of the push rule
|
// GetActions matches the given event against all of the push rule
|
||||||
// collections in this push ruleset in the order of priority as
|
// collections in this push ruleset in the order of priority as
|
||||||
@ -85,6 +85,9 @@ func (rs *PushRuleset) GetActions(room Room, event *mautrix.Event) (match PushAc
|
|||||||
arrays := []PushRuleCollection{rs.Override, rs.Content, rs.Room, rs.Sender, rs.Underride}
|
arrays := []PushRuleCollection{rs.Override, rs.Content, rs.Room, rs.Sender, rs.Underride}
|
||||||
// Loop until one of the push rule collections matches the room/event combo.
|
// Loop until one of the push rule collections matches the room/event combo.
|
||||||
for _, pra := range arrays {
|
for _, pra := range arrays {
|
||||||
|
if pra == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if match = pra.GetActions(room, event); match != nil {
|
if match = pra.GetActions(room, event); match != nil {
|
||||||
// Match found, return it.
|
// Match found, return it.
|
||||||
return
|
return
|
||||||
|
@ -57,7 +57,6 @@ type UnreadMessage struct {
|
|||||||
Highlight bool
|
Highlight bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Room represents a single Matrix room.
|
// Room represents a single Matrix room.
|
||||||
type Room struct {
|
type Room struct {
|
||||||
*mautrix.Room
|
*mautrix.Room
|
||||||
@ -101,26 +100,7 @@ type Room struct {
|
|||||||
// The list of aliases. Directly fetched from the m.room.aliases state event.
|
// The list of aliases. Directly fetched from the m.room.aliases state event.
|
||||||
aliasesCache []string
|
aliasesCache []string
|
||||||
|
|
||||||
// fetchHistoryLock is used to make sure multiple goroutines don't fetch
|
lock sync.RWMutex
|
||||||
// history for this room at the same time.
|
|
||||||
fetchHistoryLock *sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// LockHistory locks the history fetching mutex.
|
|
||||||
// If the mutex is nil, it will be created.
|
|
||||||
func (room *Room) LockHistory() {
|
|
||||||
if room.fetchHistoryLock == nil {
|
|
||||||
room.fetchHistoryLock = &sync.Mutex{}
|
|
||||||
}
|
|
||||||
room.fetchHistoryLock.Lock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnlockHistory unlocks the history fetching mutex.
|
|
||||||
// If the mutex is nil, this does nothing.
|
|
||||||
func (room *Room) UnlockHistory() {
|
|
||||||
if room.fetchHistoryLock != nil {
|
|
||||||
room.fetchHistoryLock.Unlock()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (room *Room) Load(path string) error {
|
func (room *Room) Load(path string) error {
|
||||||
@ -130,6 +110,8 @@ func (room *Room) Load(path string) error {
|
|||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
dec := gob.NewDecoder(file)
|
dec := gob.NewDecoder(file)
|
||||||
|
room.lock.Lock()
|
||||||
|
defer room.lock.Unlock()
|
||||||
return dec.Decode(room)
|
return dec.Decode(room)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,11 +122,15 @@ func (room *Room) Save(path string) error {
|
|||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
enc := gob.NewEncoder(file)
|
enc := gob.NewEncoder(file)
|
||||||
|
room.lock.RLock()
|
||||||
|
defer room.lock.RUnlock()
|
||||||
return enc.Encode(room)
|
return enc.Encode(room)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkRead clears the new message statuses on this room.
|
// MarkRead clears the new message statuses on this room.
|
||||||
func (room *Room) MarkRead(eventID string) bool {
|
func (room *Room) MarkRead(eventID string) bool {
|
||||||
|
room.lock.Lock()
|
||||||
|
defer room.lock.Unlock()
|
||||||
if room.lastMarkedRead == eventID {
|
if room.lastMarkedRead == eventID {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -164,6 +150,8 @@ func (room *Room) MarkRead(eventID string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (room *Room) UnreadCount() int {
|
func (room *Room) UnreadCount() int {
|
||||||
|
room.lock.Lock()
|
||||||
|
defer room.lock.Unlock()
|
||||||
if room.unreadCountCache == nil {
|
if room.unreadCountCache == nil {
|
||||||
room.unreadCountCache = new(int)
|
room.unreadCountCache = new(int)
|
||||||
for _, unreadMessage := range room.UnreadMessages {
|
for _, unreadMessage := range room.UnreadMessages {
|
||||||
@ -176,6 +164,8 @@ func (room *Room) UnreadCount() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (room *Room) Highlighted() bool {
|
func (room *Room) Highlighted() bool {
|
||||||
|
room.lock.Lock()
|
||||||
|
defer room.lock.Unlock()
|
||||||
if room.highlightCache == nil {
|
if room.highlightCache == nil {
|
||||||
room.highlightCache = new(bool)
|
room.highlightCache = new(bool)
|
||||||
for _, unreadMessage := range room.UnreadMessages {
|
for _, unreadMessage := range room.UnreadMessages {
|
||||||
@ -193,6 +183,8 @@ func (room *Room) HasNewMessages() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (room *Room) AddUnread(eventID string, counted, highlight bool) {
|
func (room *Room) AddUnread(eventID string, counted, highlight bool) {
|
||||||
|
room.lock.Lock()
|
||||||
|
defer room.lock.Unlock()
|
||||||
room.UnreadMessages = append(room.UnreadMessages, UnreadMessage{
|
room.UnreadMessages = append(room.UnreadMessages, UnreadMessage{
|
||||||
EventID: eventID,
|
EventID: eventID,
|
||||||
Counted: counted,
|
Counted: counted,
|
||||||
@ -213,6 +205,8 @@ func (room *Room) AddUnread(eventID string, counted, highlight bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (room *Room) Tags() []RoomTag {
|
func (room *Room) Tags() []RoomTag {
|
||||||
|
room.lock.RLock()
|
||||||
|
defer room.lock.RUnlock()
|
||||||
if len(room.RawTags) == 0 {
|
if len(room.RawTags) == 0 {
|
||||||
if room.IsDirect {
|
if room.IsDirect {
|
||||||
return []RoomTag{{"net.maunium.gomuks.fake.direct", "0.5"}}
|
return []RoomTag{{"net.maunium.gomuks.fake.direct", "0.5"}}
|
||||||
@ -225,6 +219,8 @@ func (room *Room) Tags() []RoomTag {
|
|||||||
// UpdateState updates the room's current state with the given Event. This will clobber events based
|
// UpdateState updates the room's current state with the given Event. This will clobber events based
|
||||||
// on the type/state_key combination.
|
// on the type/state_key combination.
|
||||||
func (room *Room) UpdateState(event *mautrix.Event) {
|
func (room *Room) UpdateState(event *mautrix.Event) {
|
||||||
|
room.lock.Lock()
|
||||||
|
defer room.lock.Unlock()
|
||||||
_, exists := room.State[event.Type]
|
_, exists := room.State[event.Type]
|
||||||
if !exists {
|
if !exists {
|
||||||
room.State[event.Type] = make(map[string]*mautrix.Event)
|
room.State[event.Type] = make(map[string]*mautrix.Event)
|
||||||
@ -269,13 +265,15 @@ func (room *Room) UpdateState(event *mautrix.Event) {
|
|||||||
|
|
||||||
// GetStateEvent returns the state event for the given type/state_key combo, or nil.
|
// GetStateEvent returns the state event for the given type/state_key combo, or nil.
|
||||||
func (room *Room) GetStateEvent(eventType mautrix.EventType, stateKey string) *mautrix.Event {
|
func (room *Room) GetStateEvent(eventType mautrix.EventType, stateKey string) *mautrix.Event {
|
||||||
|
room.lock.RLock()
|
||||||
|
defer room.lock.RUnlock()
|
||||||
stateEventMap, _ := room.State[eventType]
|
stateEventMap, _ := room.State[eventType]
|
||||||
event, _ := stateEventMap[stateKey]
|
event, _ := stateEventMap[stateKey]
|
||||||
return event
|
return event
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStateEvents returns the state events for the given type.
|
// getStateEvents returns the state events for the given type.
|
||||||
func (room *Room) GetStateEvents(eventType mautrix.EventType) map[string]*mautrix.Event {
|
func (room *Room) getStateEvents(eventType mautrix.EventType) map[string]*mautrix.Event {
|
||||||
stateEventMap, _ := room.State[eventType]
|
stateEventMap, _ := room.State[eventType]
|
||||||
return stateEventMap
|
return stateEventMap
|
||||||
}
|
}
|
||||||
@ -309,11 +307,13 @@ func (room *Room) GetCanonicalAlias() string {
|
|||||||
// GetAliases returns the list of aliases that point to this room.
|
// GetAliases returns the list of aliases that point to this room.
|
||||||
func (room *Room) GetAliases() []string {
|
func (room *Room) GetAliases() []string {
|
||||||
if room.aliasesCache == nil {
|
if room.aliasesCache == nil {
|
||||||
aliasEvents := room.GetStateEvents(mautrix.StateAliases)
|
room.lock.RLock()
|
||||||
|
aliasEvents := room.getStateEvents(mautrix.StateAliases)
|
||||||
room.aliasesCache = []string{}
|
room.aliasesCache = []string{}
|
||||||
for _, event := range aliasEvents {
|
for _, event := range aliasEvents {
|
||||||
room.aliasesCache = append(room.aliasesCache, event.Content.Aliases...)
|
room.aliasesCache = append(room.aliasesCache, event.Content.Aliases...)
|
||||||
}
|
}
|
||||||
|
room.lock.RUnlock()
|
||||||
}
|
}
|
||||||
return room.aliasesCache
|
return room.aliasesCache
|
||||||
}
|
}
|
||||||
@ -394,7 +394,8 @@ func (room *Room) GetTitle() string {
|
|||||||
// createMemberCache caches all member events into a easily processable MXID -> *Member map.
|
// createMemberCache caches all member events into a easily processable MXID -> *Member map.
|
||||||
func (room *Room) createMemberCache() map[string]*mautrix.Member {
|
func (room *Room) createMemberCache() map[string]*mautrix.Member {
|
||||||
cache := make(map[string]*mautrix.Member)
|
cache := make(map[string]*mautrix.Member)
|
||||||
events := room.GetStateEvents(mautrix.StateMember)
|
room.lock.RLock()
|
||||||
|
events := room.getStateEvents(mautrix.StateMember)
|
||||||
room.firstMemberCache = nil
|
room.firstMemberCache = nil
|
||||||
if events != nil {
|
if events != nil {
|
||||||
for userID, event := range events {
|
for userID, event := range events {
|
||||||
@ -411,7 +412,10 @@ func (room *Room) createMemberCache() map[string]*mautrix.Member {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
room.lock.RUnlock()
|
||||||
|
room.lock.Lock()
|
||||||
room.memberCache = cache
|
room.memberCache = cache
|
||||||
|
room.lock.Unlock()
|
||||||
return cache
|
return cache
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,7 +436,9 @@ func (room *Room) GetMember(userID string) *mautrix.Member {
|
|||||||
if len(room.memberCache) == 0 {
|
if len(room.memberCache) == 0 {
|
||||||
room.createMemberCache()
|
room.createMemberCache()
|
||||||
}
|
}
|
||||||
|
room.lock.RLock()
|
||||||
member, _ := room.memberCache[userID]
|
member, _ := room.memberCache[userID]
|
||||||
|
room.lock.RUnlock()
|
||||||
return member
|
return member
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,7 +451,6 @@ func (room *Room) GetSessionOwner() string {
|
|||||||
func NewRoom(roomID, owner string) *Room {
|
func NewRoom(roomID, owner string) *Room {
|
||||||
return &Room{
|
return &Room{
|
||||||
Room: mautrix.NewRoom(roomID),
|
Room: mautrix.NewRoom(roomID),
|
||||||
fetchHistoryLock: &sync.Mutex{},
|
|
||||||
SessionUserID: owner,
|
SessionUserID: owner,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,8 @@ func NewGomuksSyncer(session SyncerSession) *GomuksSyncer {
|
|||||||
// ProcessResponse processes a Matrix sync response.
|
// ProcessResponse processes a Matrix sync response.
|
||||||
func (s *GomuksSyncer) ProcessResponse(res *mautrix.RespSync, since string) (err error) {
|
func (s *GomuksSyncer) ProcessResponse(res *mautrix.RespSync, since string) (err error) {
|
||||||
debug.Print("Received sync response")
|
debug.Print("Received sync response")
|
||||||
|
// dat, _ := json.MarshalIndent(res, "", " ")
|
||||||
|
// debug.Print(string(dat))
|
||||||
s.processSyncEvents(nil, res.Presence.Events, EventSourcePresence)
|
s.processSyncEvents(nil, res.Presence.Events, EventSourcePresence)
|
||||||
s.processSyncEvents(nil, res.AccountData.Events, EventSourceAccountData)
|
s.processSyncEvents(nil, res.AccountData.Events, EventSourceAccountData)
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/mattn/go-runewidth"
|
"github.com/mattn/go-runewidth"
|
||||||
|
|
||||||
@ -43,19 +45,23 @@ type MessageView struct {
|
|||||||
DateFormat string
|
DateFormat string
|
||||||
TimestampFormat string
|
TimestampFormat string
|
||||||
TimestampWidth int
|
TimestampWidth int
|
||||||
LoadingMessages bool
|
|
||||||
|
|
||||||
widestSender int
|
// Used for locking
|
||||||
width int
|
loadingMessages int32
|
||||||
height int
|
|
||||||
prevWidth int
|
_widestSender uint32
|
||||||
prevHeight int
|
_width uint32
|
||||||
|
_height uint32
|
||||||
|
_prevWidth uint32
|
||||||
|
_prevHeight uint32
|
||||||
prevMsgCount int
|
prevMsgCount int
|
||||||
prevPrefs config.UserPreferences
|
prevPrefs config.UserPreferences
|
||||||
|
|
||||||
|
messageIDLock sync.RWMutex
|
||||||
messageIDs map[string]messages.UIMessage
|
messageIDs map[string]messages.UIMessage
|
||||||
|
messagesLock sync.RWMutex
|
||||||
messages []messages.UIMessage
|
messages []messages.UIMessage
|
||||||
|
msgBufferLock sync.RWMutex
|
||||||
msgBuffer []messages.UIMessage
|
msgBuffer []messages.UIMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,19 +78,20 @@ func NewMessageView(parent *RoomView) *MessageView {
|
|||||||
messageIDs: make(map[string]messages.UIMessage),
|
messageIDs: make(map[string]messages.UIMessage),
|
||||||
msgBuffer: make([]messages.UIMessage, 0),
|
msgBuffer: make([]messages.UIMessage, 0),
|
||||||
|
|
||||||
width: 80,
|
_width: 80,
|
||||||
widestSender: 5,
|
_widestSender: 5,
|
||||||
prevWidth: -1,
|
_prevWidth: 0,
|
||||||
prevHeight: -1,
|
_prevHeight: 0,
|
||||||
prevMsgCount: -1,
|
prevMsgCount: -1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MessageView) updateWidestSender(sender string) {
|
func (view *MessageView) updateWidestSender(sender string) {
|
||||||
if len(sender) > view.widestSender {
|
if len(sender) > int(view._widestSender) {
|
||||||
view.widestSender = len(sender)
|
if len(sender) > view.MaxSenderWidth {
|
||||||
if view.widestSender > view.MaxSenderWidth {
|
atomic.StoreUint32(&view._widestSender, uint32(view.MaxSenderWidth))
|
||||||
view.widestSender = view.MaxSenderWidth
|
} else {
|
||||||
|
atomic.StoreUint32(&view._widestSender, uint32(len(sender)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,22 +116,21 @@ func (view *MessageView) AddMessage(ifcMessage ifc.Message, direction MessageDir
|
|||||||
}
|
}
|
||||||
|
|
||||||
var oldMsg messages.UIMessage
|
var oldMsg messages.UIMessage
|
||||||
var messageExists bool
|
if oldMsg = view.getMessageByID(message.ID()); oldMsg != nil {
|
||||||
if oldMsg, messageExists = view.messageIDs[message.ID()]; messageExists {
|
|
||||||
view.replaceMessage(oldMsg, message)
|
view.replaceMessage(oldMsg, message)
|
||||||
direction = IgnoreMessage
|
direction = IgnoreMessage
|
||||||
} else if oldMsg, messageExists = view.messageIDs[message.TxnID()]; messageExists {
|
} else if oldMsg = view.getMessageByID(message.TxnID()); oldMsg != nil {
|
||||||
view.replaceMessage(oldMsg, message)
|
view.replaceMessage(oldMsg, message)
|
||||||
delete(view.messageIDs, message.TxnID())
|
view.deleteMessageID(message.TxnID())
|
||||||
direction = IgnoreMessage
|
direction = IgnoreMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
view.updateWidestSender(message.Sender())
|
view.updateWidestSender(message.Sender())
|
||||||
|
|
||||||
width := view.width
|
width := view.width()
|
||||||
bare := view.config.Preferences.BareMessageView
|
bare := view.config.Preferences.BareMessageView
|
||||||
if !bare {
|
if !bare {
|
||||||
width -= view.TimestampWidth + TimestampSenderGap + view.widestSender + SenderMessageGap
|
width -= view.TimestampWidth + TimestampSenderGap + view.widestSender() + SenderMessageGap
|
||||||
}
|
}
|
||||||
message.CalculateBuffer(view.config.Preferences, width)
|
message.CalculateBuffer(view.config.Preferences, width)
|
||||||
|
|
||||||
@ -140,18 +146,22 @@ func (view *MessageView) AddMessage(ifcMessage ifc.Message, direction MessageDir
|
|||||||
if view.ScrollOffset > 0 {
|
if view.ScrollOffset > 0 {
|
||||||
view.ScrollOffset += message.Height()
|
view.ScrollOffset += message.Height()
|
||||||
}
|
}
|
||||||
|
view.messagesLock.Lock()
|
||||||
if len(view.messages) > 0 && !view.messages[len(view.messages)-1].SameDate(message) {
|
if len(view.messages) > 0 && !view.messages[len(view.messages)-1].SameDate(message) {
|
||||||
view.messages = append(view.messages, makeDateChange(), message)
|
view.messages = append(view.messages, makeDateChange(), message)
|
||||||
} else {
|
} else {
|
||||||
view.messages = append(view.messages, message)
|
view.messages = append(view.messages, message)
|
||||||
}
|
}
|
||||||
|
view.messagesLock.Unlock()
|
||||||
view.appendBuffer(message)
|
view.appendBuffer(message)
|
||||||
} else if direction == PrependMessage {
|
} else if direction == PrependMessage {
|
||||||
|
view.messagesLock.Lock()
|
||||||
if len(view.messages) > 0 && !view.messages[0].SameDate(message) {
|
if len(view.messages) > 0 && !view.messages[0].SameDate(message) {
|
||||||
view.messages = append([]messages.UIMessage{message, makeDateChange()}, view.messages...)
|
view.messages = append([]messages.UIMessage{message, makeDateChange()}, view.messages...)
|
||||||
} else {
|
} else {
|
||||||
view.messages = append([]messages.UIMessage{message}, view.messages...)
|
view.messages = append([]messages.UIMessage{message}, view.messages...)
|
||||||
}
|
}
|
||||||
|
view.messagesLock.Unlock()
|
||||||
} else if oldMsg != nil {
|
} else if oldMsg != nil {
|
||||||
view.replaceBuffer(oldMsg, message)
|
view.replaceBuffer(oldMsg, message)
|
||||||
} else {
|
} else {
|
||||||
@ -160,31 +170,62 @@ func (view *MessageView) AddMessage(ifcMessage ifc.Message, direction MessageDir
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(message.ID()) > 0 {
|
if len(message.ID()) > 0 {
|
||||||
view.messageIDs[message.ID()] = message
|
view.setMessageID(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (view *MessageView) replaceMessage(original messages.UIMessage, new messages.UIMessage) {
|
||||||
|
if len(new.ID()) > 0 {
|
||||||
|
view.setMessageID(new)
|
||||||
|
}
|
||||||
|
view.messagesLock.Lock()
|
||||||
|
for index, msg := range view.messages {
|
||||||
|
if msg == original {
|
||||||
|
view.messages[index] = new
|
||||||
|
}
|
||||||
|
}
|
||||||
|
view.messagesLock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *MessageView) getMessageByID(id string) messages.UIMessage {
|
||||||
|
view.messageIDLock.RLock()
|
||||||
|
defer view.messageIDLock.RUnlock()
|
||||||
|
msg, ok := view.messageIDs[id]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *MessageView) deleteMessageID(id string) {
|
||||||
|
view.messageIDLock.Lock()
|
||||||
|
delete(view.messageIDs, id)
|
||||||
|
view.messageIDLock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *MessageView) setMessageID(message messages.UIMessage) {
|
||||||
|
view.messageIDLock.Lock()
|
||||||
|
view.messageIDs[message.ID()] = message
|
||||||
|
view.messageIDLock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
func (view *MessageView) appendBuffer(message messages.UIMessage) {
|
func (view *MessageView) appendBuffer(message messages.UIMessage) {
|
||||||
|
view.msgBufferLock.Lock()
|
||||||
|
view.appendBufferUnlocked(message)
|
||||||
|
view.msgBufferLock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *MessageView) appendBufferUnlocked(message messages.UIMessage) {
|
||||||
for i := 0; i < message.Height(); i++ {
|
for i := 0; i < message.Height(); i++ {
|
||||||
view.msgBuffer = append(view.msgBuffer, message)
|
view.msgBuffer = append(view.msgBuffer, message)
|
||||||
}
|
}
|
||||||
view.prevMsgCount++
|
view.prevMsgCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MessageView) replaceMessage(original messages.UIMessage, new messages.UIMessage) {
|
|
||||||
if len(new.ID()) > 0 {
|
|
||||||
view.messageIDs[new.ID()] = new
|
|
||||||
}
|
|
||||||
for index, msg := range view.messages {
|
|
||||||
if msg == original {
|
|
||||||
view.messages[index] = new
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (view *MessageView) replaceBuffer(original messages.UIMessage, new messages.UIMessage) {
|
func (view *MessageView) replaceBuffer(original messages.UIMessage, new messages.UIMessage) {
|
||||||
start := -1
|
start := -1
|
||||||
end := -1
|
end := -1
|
||||||
|
view.msgBufferLock.RLock()
|
||||||
for index, meta := range view.msgBuffer {
|
for index, meta := range view.msgBuffer {
|
||||||
if meta == original {
|
if meta == original {
|
||||||
if start == -1 {
|
if start == -1 {
|
||||||
@ -195,6 +236,7 @@ func (view *MessageView) replaceBuffer(original messages.UIMessage, new messages
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
view.msgBufferLock.RUnlock()
|
||||||
|
|
||||||
if start == -1 {
|
if start == -1 {
|
||||||
debug.Print("Called replaceBuffer() with message that was not in the buffer:", original)
|
debug.Print("Called replaceBuffer() with message that was not in the buffer:", original)
|
||||||
@ -208,9 +250,10 @@ func (view *MessageView) replaceBuffer(original messages.UIMessage, new messages
|
|||||||
}
|
}
|
||||||
|
|
||||||
if new.Height() == 0 {
|
if new.Height() == 0 {
|
||||||
new.CalculateBuffer(view.prevPrefs, view.prevWidth)
|
new.CalculateBuffer(view.prevPrefs, view.prevWidth())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
view.msgBufferLock.Lock()
|
||||||
if new.Height() != end-start {
|
if new.Height() != end-start {
|
||||||
metaBuffer := view.msgBuffer[0:start]
|
metaBuffer := view.msgBuffer[0:start]
|
||||||
for i := 0; i < new.Height(); i++ {
|
for i := 0; i < new.Height(); i++ {
|
||||||
@ -222,17 +265,20 @@ func (view *MessageView) replaceBuffer(original messages.UIMessage, new messages
|
|||||||
view.msgBuffer[i] = new
|
view.msgBuffer[i] = new
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
view.msgBufferLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MessageView) recalculateBuffers() {
|
func (view *MessageView) recalculateBuffers() {
|
||||||
prefs := view.config.Preferences
|
prefs := view.config.Preferences
|
||||||
recalculateMessageBuffers := view.width != view.prevWidth ||
|
recalculateMessageBuffers := view.width() != view.prevWidth() ||
|
||||||
view.prevPrefs.BareMessageView != prefs.BareMessageView ||
|
view.prevPrefs.BareMessageView != prefs.BareMessageView ||
|
||||||
view.prevPrefs.DisableImages != prefs.DisableImages
|
view.prevPrefs.DisableImages != prefs.DisableImages
|
||||||
|
view.messagesLock.RLock()
|
||||||
|
view.msgBufferLock.Lock()
|
||||||
if recalculateMessageBuffers || len(view.messages) != view.prevMsgCount {
|
if recalculateMessageBuffers || len(view.messages) != view.prevMsgCount {
|
||||||
width := view.width
|
width := view.width()
|
||||||
if !prefs.BareMessageView {
|
if !prefs.BareMessageView {
|
||||||
width -= view.TimestampWidth + TimestampSenderGap + view.widestSender + SenderMessageGap
|
width -= view.TimestampWidth + TimestampSenderGap + view.widestSender() + SenderMessageGap
|
||||||
}
|
}
|
||||||
view.msgBuffer = []messages.UIMessage{}
|
view.msgBuffer = []messages.UIMessage{}
|
||||||
view.prevMsgCount = 0
|
view.prevMsgCount = 0
|
||||||
@ -244,11 +290,12 @@ func (view *MessageView) recalculateBuffers() {
|
|||||||
if recalculateMessageBuffers {
|
if recalculateMessageBuffers {
|
||||||
message.CalculateBuffer(prefs, width)
|
message.CalculateBuffer(prefs, width)
|
||||||
}
|
}
|
||||||
view.appendBuffer(message)
|
view.appendBufferUnlocked(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
view.prevHeight = view.height
|
view.msgBufferLock.Unlock()
|
||||||
view.prevWidth = view.width
|
view.messagesLock.RUnlock()
|
||||||
|
view.updatePrevSize()
|
||||||
view.prevPrefs = prefs
|
view.prevPrefs = prefs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,19 +356,21 @@ func (view *MessageView) OnMouseEvent(event mauview.MouseEvent) bool {
|
|||||||
return true
|
return true
|
||||||
case tcell.Button1:
|
case tcell.Button1:
|
||||||
x, y := event.Position()
|
x, y := event.Position()
|
||||||
line := view.TotalHeight() - view.ScrollOffset - view.height + y
|
line := view.TotalHeight() - view.ScrollOffset - view.Height() + y
|
||||||
if line < 0 || line >= view.TotalHeight() {
|
if line < 0 || line >= view.TotalHeight() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
view.msgBufferLock.RLock()
|
||||||
message := view.msgBuffer[line]
|
message := view.msgBuffer[line]
|
||||||
var prevMessage messages.UIMessage
|
var prevMessage messages.UIMessage
|
||||||
if y != 0 && line > 0 {
|
if y != 0 && line > 0 {
|
||||||
prevMessage = view.msgBuffer[line-1]
|
prevMessage = view.msgBuffer[line-1]
|
||||||
}
|
}
|
||||||
|
view.msgBufferLock.RUnlock()
|
||||||
|
|
||||||
usernameX := view.TimestampWidth + TimestampSenderGap
|
usernameX := view.TimestampWidth + TimestampSenderGap
|
||||||
messageX := usernameX + view.widestSender + SenderMessageGap
|
messageX := usernameX + view.widestSender() + SenderMessageGap
|
||||||
|
|
||||||
if x >= messageX {
|
if x >= messageX {
|
||||||
return view.handleMessageClick(message)
|
return view.handleMessageClick(message)
|
||||||
@ -336,30 +385,59 @@ const PaddingAtTop = 5
|
|||||||
|
|
||||||
func (view *MessageView) AddScrollOffset(diff int) {
|
func (view *MessageView) AddScrollOffset(diff int) {
|
||||||
totalHeight := view.TotalHeight()
|
totalHeight := view.TotalHeight()
|
||||||
if diff >= 0 && view.ScrollOffset+diff >= totalHeight-view.height+PaddingAtTop {
|
height := view.Height()
|
||||||
view.ScrollOffset = totalHeight - view.height + PaddingAtTop
|
if diff >= 0 && view.ScrollOffset+diff >= totalHeight-height+PaddingAtTop {
|
||||||
|
view.ScrollOffset = totalHeight - height + PaddingAtTop
|
||||||
} else {
|
} else {
|
||||||
view.ScrollOffset += diff
|
view.ScrollOffset += diff
|
||||||
}
|
}
|
||||||
|
|
||||||
if view.ScrollOffset > totalHeight-view.height+PaddingAtTop {
|
if view.ScrollOffset > totalHeight-height+PaddingAtTop {
|
||||||
view.ScrollOffset = totalHeight - view.height + PaddingAtTop
|
view.ScrollOffset = totalHeight - height + PaddingAtTop
|
||||||
}
|
}
|
||||||
if view.ScrollOffset < 0 {
|
if view.ScrollOffset < 0 {
|
||||||
view.ScrollOffset = 0
|
view.ScrollOffset = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (view *MessageView) setSize(width, height int) {
|
||||||
|
atomic.StoreUint32(&view._width, uint32(width))
|
||||||
|
atomic.StoreUint32(&view._height, uint32(height))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *MessageView) updatePrevSize() {
|
||||||
|
atomic.StoreUint32(&view._prevWidth, atomic.LoadUint32(&view._width))
|
||||||
|
atomic.StoreUint32(&view._prevHeight, atomic.LoadUint32(&view._height))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *MessageView) prevHeight() int {
|
||||||
|
return int(atomic.LoadUint32(&view._prevHeight))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *MessageView) prevWidth() int {
|
||||||
|
return int(atomic.LoadUint32(&view._prevWidth))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *MessageView) widestSender() int {
|
||||||
|
return int(atomic.LoadUint32(&view._widestSender))
|
||||||
|
}
|
||||||
|
|
||||||
func (view *MessageView) Height() int {
|
func (view *MessageView) Height() int {
|
||||||
return view.height
|
return int(atomic.LoadUint32(&view._height))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *MessageView) width() int {
|
||||||
|
return int(atomic.LoadUint32(&view._width))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MessageView) TotalHeight() int {
|
func (view *MessageView) TotalHeight() int {
|
||||||
|
view.msgBufferLock.RLock()
|
||||||
|
defer view.msgBufferLock.RUnlock()
|
||||||
return len(view.msgBuffer)
|
return len(view.msgBuffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MessageView) IsAtTop() bool {
|
func (view *MessageView) IsAtTop() bool {
|
||||||
return view.ScrollOffset >= len(view.msgBuffer)-view.height+PaddingAtTop
|
return view.ScrollOffset >= view.TotalHeight()-view.Height()+PaddingAtTop
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -407,7 +485,7 @@ func (view *MessageView) getIndexOffset(screen mauview.Screen, height, messageX
|
|||||||
indexOffset = view.TotalHeight() - view.ScrollOffset - height
|
indexOffset = view.TotalHeight() - view.ScrollOffset - height
|
||||||
if indexOffset <= -PaddingAtTop {
|
if indexOffset <= -PaddingAtTop {
|
||||||
message := "Scroll up to load more messages."
|
message := "Scroll up to load more messages."
|
||||||
if view.LoadingMessages {
|
if atomic.LoadInt32(&view.loadingMessages) == 1 {
|
||||||
message = "Loading more messages..."
|
message = "Loading more messages..."
|
||||||
}
|
}
|
||||||
widget.WriteLineSimpleColor(screen, message, messageX, 0, tcell.ColorGreen)
|
widget.WriteLineSimpleColor(screen, message, messageX, 0, tcell.ColorGreen)
|
||||||
@ -419,6 +497,7 @@ func (view *MessageView) CapturePlaintext(height int) string {
|
|||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
indexOffset := view.TotalHeight() - view.ScrollOffset - height
|
indexOffset := view.TotalHeight() - view.ScrollOffset - height
|
||||||
var prevMessage messages.UIMessage
|
var prevMessage messages.UIMessage
|
||||||
|
view.msgBufferLock.RLock()
|
||||||
for line := 0; line < height; line++ {
|
for line := 0; line < height; line++ {
|
||||||
index := indexOffset + line
|
index := indexOffset + line
|
||||||
if index < 0 {
|
if index < 0 {
|
||||||
@ -438,27 +517,29 @@ func (view *MessageView) CapturePlaintext(height int) string {
|
|||||||
prevMessage = message
|
prevMessage = message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
view.msgBufferLock.RUnlock()
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MessageView) Draw(screen mauview.Screen) {
|
func (view *MessageView) Draw(screen mauview.Screen) {
|
||||||
view.width, view.height = screen.Size()
|
view.setSize(screen.Size())
|
||||||
view.recalculateBuffers()
|
view.recalculateBuffers()
|
||||||
|
|
||||||
|
height := view.Height()
|
||||||
if view.TotalHeight() == 0 {
|
if view.TotalHeight() == 0 {
|
||||||
widget.WriteLineSimple(screen, "It's quite empty in here.", 0, view.height)
|
widget.WriteLineSimple(screen, "It's quite empty in here.", 0, height)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
usernameX := view.TimestampWidth + TimestampSenderGap
|
usernameX := view.TimestampWidth + TimestampSenderGap
|
||||||
messageX := usernameX + view.widestSender + SenderMessageGap
|
messageX := usernameX + view.widestSender() + SenderMessageGap
|
||||||
|
|
||||||
bareMode := view.config.Preferences.BareMessageView
|
bareMode := view.config.Preferences.BareMessageView
|
||||||
if bareMode {
|
if bareMode {
|
||||||
messageX = 0
|
messageX = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
indexOffset := view.getIndexOffset(screen, view.height, messageX)
|
indexOffset := view.getIndexOffset(screen, height, messageX)
|
||||||
|
|
||||||
viewStart := 0
|
viewStart := 0
|
||||||
if indexOffset < 0 {
|
if indexOffset < 0 {
|
||||||
@ -466,13 +547,13 @@ func (view *MessageView) Draw(screen mauview.Screen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !bareMode {
|
if !bareMode {
|
||||||
separatorX := usernameX + view.widestSender + SenderSeparatorGap
|
separatorX := usernameX + view.widestSender() + SenderSeparatorGap
|
||||||
scrollBarHeight, scrollBarPos := view.calculateScrollBar(view.height)
|
scrollBarHeight, scrollBarPos := view.calculateScrollBar(height)
|
||||||
|
|
||||||
for line := viewStart; line < view.height; line++ {
|
for line := viewStart; line < height; line++ {
|
||||||
showScrollbar := line-viewStart >= scrollBarPos-scrollBarHeight && line-viewStart < scrollBarPos
|
showScrollbar := line-viewStart >= scrollBarPos-scrollBarHeight && line-viewStart < scrollBarPos
|
||||||
isTop := line == viewStart && view.ScrollOffset+view.height >= view.TotalHeight()
|
isTop := line == viewStart && view.ScrollOffset+height >= view.TotalHeight()
|
||||||
isBottom := line == view.height-1 && view.ScrollOffset == 0
|
isBottom := line == height-1 && view.ScrollOffset == 0
|
||||||
|
|
||||||
borderChar, borderStyle := getScrollbarStyle(showScrollbar, isTop, isBottom)
|
borderChar, borderStyle := getScrollbarStyle(showScrollbar, isTop, isBottom)
|
||||||
|
|
||||||
@ -481,7 +562,8 @@ func (view *MessageView) Draw(screen mauview.Screen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var prevMsg messages.UIMessage
|
var prevMsg messages.UIMessage
|
||||||
for line := viewStart; line < view.height && indexOffset+line < view.TotalHeight(); line++ {
|
view.msgBufferLock.RLock()
|
||||||
|
for line := viewStart; line < height && indexOffset+line < len(view.msgBuffer); line++ {
|
||||||
index := indexOffset + line
|
index := indexOffset + line
|
||||||
|
|
||||||
msg := view.msgBuffer[index]
|
msg := view.msgBuffer[index]
|
||||||
@ -493,7 +575,7 @@ func (view *MessageView) Draw(screen mauview.Screen) {
|
|||||||
//if !bareMode && (prevMsg == nil || meta.Sender() != prevMsg.Sender()) {
|
//if !bareMode && (prevMsg == nil || meta.Sender() != prevMsg.Sender()) {
|
||||||
widget.WriteLineColor(
|
widget.WriteLineColor(
|
||||||
screen, mauview.AlignRight, msg.Sender(),
|
screen, mauview.AlignRight, msg.Sender(),
|
||||||
usernameX, line, view.widestSender,
|
usernameX, line, view.widestSender(),
|
||||||
msg.SenderColor())
|
msg.SenderColor())
|
||||||
//}
|
//}
|
||||||
prevMsg = msg
|
prevMsg = msg
|
||||||
@ -502,7 +584,8 @@ func (view *MessageView) Draw(screen mauview.Screen) {
|
|||||||
for i := index - 1; i >= 0 && view.msgBuffer[i] == msg; i-- {
|
for i := index - 1; i >= 0 && view.msgBuffer[i] == msg; i-- {
|
||||||
line--
|
line--
|
||||||
}
|
}
|
||||||
msg.Draw(mauview.NewProxyScreen(screen, messageX, line, view.width-messageX, msg.Height()))
|
msg.Draw(mauview.NewProxyScreen(screen, messageX, line, view.width()-messageX, msg.Height()))
|
||||||
line += msg.Height() - 1
|
line += msg.Height() - 1
|
||||||
}
|
}
|
||||||
|
view.msgBufferLock.RUnlock()
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"maunium.net/go/mauview"
|
"maunium.net/go/mauview"
|
||||||
"maunium.net/go/tcell"
|
"maunium.net/go/tcell"
|
||||||
@ -29,6 +30,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type RoomList struct {
|
type RoomList struct {
|
||||||
|
sync.RWMutex
|
||||||
|
|
||||||
parent *MainView
|
parent *MainView
|
||||||
|
|
||||||
// The list of tags in display order.
|
// The list of tags in display order.
|
||||||
@ -71,6 +74,8 @@ func NewRoomList(parent *MainView) *RoomList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) Contains(roomID string) bool {
|
func (list *RoomList) Contains(roomID string) bool {
|
||||||
|
list.RLock()
|
||||||
|
defer list.RUnlock()
|
||||||
for _, trl := range list.items {
|
for _, trl := range list.items {
|
||||||
for _, room := range trl.All() {
|
for _, room := range trl.All() {
|
||||||
if room.ID == roomID {
|
if room.ID == roomID {
|
||||||
@ -88,8 +93,8 @@ func (list *RoomList) Add(room *rooms.Room) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) CheckTag(tag string) {
|
func (list *RoomList) checkTag(tag string) {
|
||||||
index := list.IndexTag(tag)
|
index := list.indexTag(tag)
|
||||||
|
|
||||||
trl, ok := list.items[tag]
|
trl, ok := list.items[tag]
|
||||||
|
|
||||||
@ -107,6 +112,8 @@ func (list *RoomList) CheckTag(tag string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) AddToTag(tag rooms.RoomTag, room *rooms.Room) {
|
func (list *RoomList) AddToTag(tag rooms.RoomTag, room *rooms.Room) {
|
||||||
|
list.Lock()
|
||||||
|
defer list.Unlock()
|
||||||
trl, ok := list.items[tag.Tag]
|
trl, ok := list.items[tag.Tag]
|
||||||
if !ok {
|
if !ok {
|
||||||
list.items[tag.Tag] = NewTagRoomList(list, tag.Tag, NewDefaultOrderedRoom(room))
|
list.items[tag.Tag] = NewTagRoomList(list, tag.Tag, NewDefaultOrderedRoom(room))
|
||||||
@ -114,7 +121,7 @@ func (list *RoomList) AddToTag(tag rooms.RoomTag, room *rooms.Room) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trl.Insert(tag.Order, room)
|
trl.Insert(tag.Order, room)
|
||||||
list.CheckTag(tag.Tag)
|
list.checkTag(tag.Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) Remove(room *rooms.Room) {
|
func (list *RoomList) Remove(room *rooms.Room) {
|
||||||
@ -124,6 +131,8 @@ func (list *RoomList) Remove(room *rooms.Room) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) RemoveFromTag(tag string, room *rooms.Room) {
|
func (list *RoomList) RemoveFromTag(tag string, room *rooms.Room) {
|
||||||
|
list.Lock()
|
||||||
|
defer list.Unlock()
|
||||||
trl, ok := list.items[tag]
|
trl, ok := list.items[tag]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
@ -158,10 +167,12 @@ func (list *RoomList) RemoveFromTag(tag string, room *rooms.Room) {
|
|||||||
list.selectedTag = ""
|
list.selectedTag = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list.CheckTag(tag)
|
list.checkTag(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) Bump(room *rooms.Room) {
|
func (list *RoomList) Bump(room *rooms.Room) {
|
||||||
|
list.RLock()
|
||||||
|
defer list.RUnlock()
|
||||||
for _, tag := range room.Tags() {
|
for _, tag := range room.Tags() {
|
||||||
trl, ok := list.items[tag.Tag]
|
trl, ok := list.items[tag.Tag]
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -172,6 +183,8 @@ func (list *RoomList) Bump(room *rooms.Room) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) Clear() {
|
func (list *RoomList) Clear() {
|
||||||
|
list.Lock()
|
||||||
|
defer list.Unlock()
|
||||||
list.items = make(map[string]*TagRoomList)
|
list.items = make(map[string]*TagRoomList)
|
||||||
list.tags = []string{"m.favourite", "net.maunium.gomuks.fake.direct", "", "m.lowpriority"}
|
list.tags = []string{"m.favourite", "net.maunium.gomuks.fake.direct", "", "m.lowpriority"}
|
||||||
for _, tag := range list.tags {
|
for _, tag := range list.tags {
|
||||||
@ -220,6 +233,8 @@ func (list *RoomList) AddScrollOffset(offset int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) First() (string, *rooms.Room) {
|
func (list *RoomList) First() (string, *rooms.Room) {
|
||||||
|
list.RLock()
|
||||||
|
defer list.RUnlock()
|
||||||
for _, tag := range list.tags {
|
for _, tag := range list.tags {
|
||||||
trl := list.items[tag]
|
trl := list.items[tag]
|
||||||
if trl.HasVisibleRooms() {
|
if trl.HasVisibleRooms() {
|
||||||
@ -230,6 +245,8 @@ func (list *RoomList) First() (string, *rooms.Room) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) Last() (string, *rooms.Room) {
|
func (list *RoomList) Last() (string, *rooms.Room) {
|
||||||
|
list.RLock()
|
||||||
|
defer list.RUnlock()
|
||||||
for tagIndex := len(list.tags) - 1; tagIndex >= 0; tagIndex-- {
|
for tagIndex := len(list.tags) - 1; tagIndex >= 0; tagIndex-- {
|
||||||
tag := list.tags[tagIndex]
|
tag := list.tags[tagIndex]
|
||||||
trl := list.items[tag]
|
trl := list.items[tag]
|
||||||
@ -240,7 +257,7 @@ func (list *RoomList) Last() (string, *rooms.Room) {
|
|||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) IndexTag(tag string) int {
|
func (list *RoomList) indexTag(tag string) int {
|
||||||
for index, entry := range list.tags {
|
for index, entry := range list.tags {
|
||||||
if tag == entry {
|
if tag == entry {
|
||||||
return index
|
return index
|
||||||
@ -250,6 +267,8 @@ func (list *RoomList) IndexTag(tag string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) Previous() (string, *rooms.Room) {
|
func (list *RoomList) Previous() (string, *rooms.Room) {
|
||||||
|
list.RLock()
|
||||||
|
defer list.RUnlock()
|
||||||
if len(list.items) == 0 {
|
if len(list.items) == 0 {
|
||||||
return "", nil
|
return "", nil
|
||||||
} else if list.selected == nil {
|
} else if list.selected == nil {
|
||||||
@ -266,7 +285,7 @@ func (list *RoomList) Previous() (string, *rooms.Room) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if index == trl.Length()-1 {
|
if index == trl.Length()-1 {
|
||||||
tagIndex := list.IndexTag(list.selectedTag)
|
tagIndex := list.indexTag(list.selectedTag)
|
||||||
tagIndex--
|
tagIndex--
|
||||||
for ; tagIndex >= 0; tagIndex-- {
|
for ; tagIndex >= 0; tagIndex-- {
|
||||||
prevTag := list.tags[tagIndex]
|
prevTag := list.tags[tagIndex]
|
||||||
@ -283,6 +302,8 @@ func (list *RoomList) Previous() (string, *rooms.Room) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) Next() (string, *rooms.Room) {
|
func (list *RoomList) Next() (string, *rooms.Room) {
|
||||||
|
list.RLock()
|
||||||
|
defer list.RUnlock()
|
||||||
if len(list.items) == 0 {
|
if len(list.items) == 0 {
|
||||||
return "", nil
|
return "", nil
|
||||||
} else if list.selected == nil {
|
} else if list.selected == nil {
|
||||||
@ -299,7 +320,7 @@ func (list *RoomList) Next() (string, *rooms.Room) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
tagIndex := list.IndexTag(list.selectedTag)
|
tagIndex := list.indexTag(list.selectedTag)
|
||||||
tagIndex++
|
tagIndex++
|
||||||
for ; tagIndex < len(list.tags); tagIndex++ {
|
for ; tagIndex < len(list.tags); tagIndex++ {
|
||||||
nextTag := list.tags[tagIndex]
|
nextTag := list.tags[tagIndex]
|
||||||
@ -325,6 +346,8 @@ func (list *RoomList) Next() (string, *rooms.Room) {
|
|||||||
//
|
//
|
||||||
// TODO: Sorting. Now just finds first room with new messages.
|
// TODO: Sorting. Now just finds first room with new messages.
|
||||||
func (list *RoomList) NextWithActivity() (string, *rooms.Room) {
|
func (list *RoomList) NextWithActivity() (string, *rooms.Room) {
|
||||||
|
list.RLock()
|
||||||
|
defer list.RUnlock()
|
||||||
for tag, trl := range list.items {
|
for tag, trl := range list.items {
|
||||||
for _, room := range trl.All() {
|
for _, room := range trl.All() {
|
||||||
if room.HasNewMessages() {
|
if room.HasNewMessages() {
|
||||||
@ -337,7 +360,7 @@ func (list *RoomList) NextWithActivity() (string, *rooms.Room) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) index(tag string, room *rooms.Room) int {
|
func (list *RoomList) index(tag string, room *rooms.Room) int {
|
||||||
tagIndex := list.IndexTag(tag)
|
tagIndex := list.indexTag(tag)
|
||||||
if tagIndex == -1 {
|
if tagIndex == -1 {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
@ -358,6 +381,7 @@ func (list *RoomList) index(tag string, room *rooms.Room) int {
|
|||||||
if tagIndex > 0 {
|
if tagIndex > 0 {
|
||||||
for i := 0; i < tagIndex; i++ {
|
for i := 0; i < tagIndex; i++ {
|
||||||
prevTag := list.tags[i]
|
prevTag := list.tags[i]
|
||||||
|
|
||||||
prevTRL := list.items[prevTag]
|
prevTRL := list.items[prevTag]
|
||||||
localIndex += prevTRL.RenderHeight()
|
localIndex += prevTRL.RenderHeight()
|
||||||
}
|
}
|
||||||
@ -367,9 +391,11 @@ func (list *RoomList) index(tag string, room *rooms.Room) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) ContentHeight() (height int) {
|
func (list *RoomList) ContentHeight() (height int) {
|
||||||
|
list.RLock()
|
||||||
for _, tag := range list.tags {
|
for _, tag := range list.tags {
|
||||||
height += list.items[tag].RenderHeight()
|
height += list.items[tag].RenderHeight()
|
||||||
}
|
}
|
||||||
|
list.RUnlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,6 +436,8 @@ func (list *RoomList) clickRoom(line, column int, mod bool) bool {
|
|||||||
if line < 0 {
|
if line < 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
list.RLock()
|
||||||
|
defer list.RUnlock()
|
||||||
for _, tag := range list.tags {
|
for _, tag := range list.tags {
|
||||||
trl := list.items[tag]
|
trl := list.items[tag]
|
||||||
if line--; line == -1 {
|
if line--; line == -1 {
|
||||||
@ -484,6 +512,7 @@ func (list *RoomList) Draw(screen mauview.Screen) {
|
|||||||
y -= list.scrollOffset
|
y -= list.scrollOffset
|
||||||
|
|
||||||
// Draw the list items.
|
// Draw the list items.
|
||||||
|
list.RLock()
|
||||||
for _, tag := range list.tags {
|
for _, tag := range list.tags {
|
||||||
trl := list.items[tag]
|
trl := list.items[tag]
|
||||||
tagDisplayName := list.GetTagDisplayName(tag)
|
tagDisplayName := list.GetTagDisplayName(tag)
|
||||||
@ -501,4 +530,5 @@ func (list *RoomList) Draw(screen mauview.Screen) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
list.RUnlock()
|
||||||
}
|
}
|
||||||
|
@ -277,7 +277,7 @@ func (trl *TagRoomList) Draw(screen mauview.Screen) {
|
|||||||
screen.SetCell(width-1, 0, tcell.StyleDefault, '▼')
|
screen.SetCell(width-1, 0, tcell.StyleDefault, '▼')
|
||||||
|
|
||||||
y := 1
|
y := 1
|
||||||
for i := trl.Length() - 1; i >= 0; i-- {
|
for i := len(items) - 1; i >= 0; i-- {
|
||||||
if y >= height {
|
if y >= height {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
113
ui/view-main.go
113
ui/view-main.go
@ -20,6 +20,8 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
@ -42,6 +44,7 @@ type MainView struct {
|
|||||||
roomView *mauview.Box
|
roomView *mauview.Box
|
||||||
currentRoom *RoomView
|
currentRoom *RoomView
|
||||||
rooms map[string]*RoomView
|
rooms map[string]*RoomView
|
||||||
|
roomsLock sync.RWMutex
|
||||||
cmdProcessor *CommandProcessor
|
cmdProcessor *CommandProcessor
|
||||||
focused mauview.Focusable
|
focused mauview.Focusable
|
||||||
|
|
||||||
@ -245,13 +248,17 @@ func (view *MainView) Blur() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) SwitchRoom(tag string, room *rooms.Room) {
|
func (view *MainView) SwitchRoom(tag string, room *rooms.Room) {
|
||||||
|
view.switchRoom(tag, room, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *MainView) switchRoom(tag string, room *rooms.Room, lock bool) {
|
||||||
if room == nil {
|
if room == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
roomView := view.rooms[room.ID]
|
roomView, ok := view.getRoomView(room.ID, lock)
|
||||||
if roomView == nil {
|
if !ok {
|
||||||
debug.Print("Tried to switch to non-nil room with nil roomView!")
|
debug.Print("Tried to switch to room with nonexistent roomView!")
|
||||||
debug.Print(tag, room)
|
debug.Print(tag, room)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -265,7 +272,7 @@ func (view *MainView) SwitchRoom(tag string, room *rooms.Room) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) addRoomPage(room *rooms.Room) {
|
func (view *MainView) addRoomPage(room *rooms.Room) *RoomView {
|
||||||
if _, ok := view.rooms[room.ID]; !ok {
|
if _, ok := view.rooms[room.ID]; !ok {
|
||||||
roomView := NewRoomView(view, room).
|
roomView := NewRoomView(view, room).
|
||||||
SetInputChangedFunc(view.InputChanged)
|
SetInputChangedFunc(view.InputChanged)
|
||||||
@ -276,53 +283,73 @@ func (view *MainView) addRoomPage(room *rooms.Room) {
|
|||||||
if len(roomView.MessageView().messages) == 0 {
|
if len(roomView.MessageView().messages) == 0 {
|
||||||
go view.LoadHistory(room.ID)
|
go view.LoadHistory(room.ID)
|
||||||
}
|
}
|
||||||
|
return roomView
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) GetRoom(roomID string) ifc.RoomView {
|
func (view *MainView) GetRoom(roomID string) ifc.RoomView {
|
||||||
room, ok := view.rooms[roomID]
|
room, ok := view.getRoomView(roomID, true)
|
||||||
if !ok {
|
if !ok {
|
||||||
view.AddRoom(view.matrix.GetRoom(roomID))
|
return view.addRoom(view.matrix.GetRoom(roomID))
|
||||||
room, ok := view.rooms[roomID]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
return room
|
return room
|
||||||
}
|
}
|
||||||
return room
|
|
||||||
|
func (view *MainView) getRoomView(roomID string, lock bool) (room *RoomView, ok bool) {
|
||||||
|
if lock {
|
||||||
|
view.roomsLock.RLock()
|
||||||
|
room, ok = view.rooms[roomID]
|
||||||
|
view.roomsLock.RUnlock()
|
||||||
|
} else {
|
||||||
|
room, ok = view.rooms[roomID]
|
||||||
|
}
|
||||||
|
return room, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) AddRoom(room *rooms.Room) {
|
func (view *MainView) AddRoom(room *rooms.Room) {
|
||||||
if view.roomList.Contains(room.ID) {
|
view.addRoom(room)
|
||||||
debug.Print("Add aborted (room exists)", room.ID, room.GetTitle())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
debug.Print("Adding", room.ID, room.GetTitle())
|
|
||||||
view.roomList.Add(room)
|
|
||||||
view.addRoomPage(room)
|
|
||||||
if !view.roomList.HasSelected() {
|
|
||||||
view.SwitchRoom(view.roomList.First())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) RemoveRoom(room *rooms.Room) {
|
func (view *MainView) RemoveRoom(room *rooms.Room) {
|
||||||
roomView := view.GetRoom(room.ID)
|
view.roomsLock.Lock()
|
||||||
if roomView == nil {
|
_, ok := view.getRoomView(room.ID, false)
|
||||||
|
if !ok {
|
||||||
|
view.roomsLock.Unlock()
|
||||||
debug.Print("Remove aborted (not found)", room.ID, room.GetTitle())
|
debug.Print("Remove aborted (not found)", room.ID, room.GetTitle())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
debug.Print("Removing", room.ID, room.GetTitle())
|
debug.Print("Removing", room.ID, room.GetTitle())
|
||||||
|
|
||||||
view.roomList.Remove(room)
|
view.roomList.Remove(room)
|
||||||
view.SwitchRoom(view.roomList.Selected())
|
t, r := view.roomList.Selected()
|
||||||
|
view.switchRoom(t, r, false)
|
||||||
delete(view.rooms, room.ID)
|
delete(view.rooms, room.ID)
|
||||||
|
view.roomsLock.Unlock()
|
||||||
|
|
||||||
view.parent.Render()
|
view.parent.Render()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (view *MainView) addRoom(room *rooms.Room) *RoomView {
|
||||||
|
if view.roomList.Contains(room.ID) {
|
||||||
|
debug.Print("Add aborted (room exists)", room.ID, room.GetTitle())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
debug.Print("Adding", room.ID, room.GetTitle())
|
||||||
|
view.roomList.Add(room)
|
||||||
|
view.roomsLock.Lock()
|
||||||
|
roomView := view.addRoomPage(room)
|
||||||
|
if !view.roomList.HasSelected() {
|
||||||
|
t, r := view.roomList.First()
|
||||||
|
view.switchRoom(t, r, false)
|
||||||
|
}
|
||||||
|
view.roomsLock.Unlock()
|
||||||
|
return roomView
|
||||||
|
}
|
||||||
|
|
||||||
func (view *MainView) SetRooms(rooms map[string]*rooms.Room) {
|
func (view *MainView) SetRooms(rooms map[string]*rooms.Room) {
|
||||||
view.roomList.Clear()
|
view.roomList.Clear()
|
||||||
|
view.roomsLock.Lock()
|
||||||
view.rooms = make(map[string]*RoomView)
|
view.rooms = make(map[string]*RoomView)
|
||||||
for _, room := range rooms {
|
for _, room := range rooms {
|
||||||
if room.HasLeft {
|
if room.HasLeft {
|
||||||
@ -331,7 +358,9 @@ func (view *MainView) SetRooms(rooms map[string]*rooms.Room) {
|
|||||||
view.roomList.Add(room)
|
view.roomList.Add(room)
|
||||||
view.addRoomPage(room)
|
view.addRoomPage(room)
|
||||||
}
|
}
|
||||||
view.SwitchRoom(view.roomList.First())
|
t, r := view.roomList.First()
|
||||||
|
view.switchRoom(t, r, false)
|
||||||
|
view.roomsLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) UpdateTags(room *rooms.Room) {
|
func (view *MainView) UpdateTags(room *rooms.Room) {
|
||||||
@ -342,8 +371,8 @@ func (view *MainView) UpdateTags(room *rooms.Room) {
|
|||||||
view.roomList.Add(room)
|
view.roomList.Add(room)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) SetTyping(room string, users []string) {
|
func (view *MainView) SetTyping(roomID string, users []string) {
|
||||||
roomView, ok := view.rooms[room]
|
roomView, ok := view.getRoomView(roomID, true)
|
||||||
if ok {
|
if ok {
|
||||||
roomView.SetTyping(users)
|
roomView.SetTyping(users)
|
||||||
view.parent.Render()
|
view.parent.Render()
|
||||||
@ -392,33 +421,27 @@ func (view *MainView) NotifyMessage(room *rooms.Room, message ifc.Message, shoul
|
|||||||
|
|
||||||
func (view *MainView) InitialSyncDone() {
|
func (view *MainView) InitialSyncDone() {
|
||||||
view.roomList.Clear()
|
view.roomList.Clear()
|
||||||
|
view.roomsLock.RLock()
|
||||||
for _, room := range view.rooms {
|
for _, room := range view.rooms {
|
||||||
view.roomList.Add(room.Room)
|
view.roomList.Add(room.Room)
|
||||||
room.UpdateUserList()
|
room.UpdateUserList()
|
||||||
}
|
}
|
||||||
|
view.roomsLock.RUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) LoadHistory(room string) {
|
func (view *MainView) LoadHistory(roomID string) {
|
||||||
defer debug.Recover()
|
defer debug.Recover()
|
||||||
roomView := view.rooms[room]
|
roomView, ok := view.getRoomView(roomID, true)
|
||||||
msgView := roomView.MessageView()
|
if !ok {
|
||||||
|
|
||||||
batch := roomView.Room.PrevBatch
|
|
||||||
lockTime := time.Now().Unix() + 1
|
|
||||||
|
|
||||||
roomView.Room.LockHistory()
|
|
||||||
msgView.LoadingMessages = true
|
|
||||||
defer func() {
|
|
||||||
roomView.Room.UnlockHistory()
|
|
||||||
msgView.LoadingMessages = false
|
|
||||||
}()
|
|
||||||
|
|
||||||
// There's no clean way to try to lock a mutex, so we just check if we still
|
|
||||||
// want to continue after we get the lock. This function should always be ran
|
|
||||||
// in a goroutine, so the blocking doesn't matter.
|
|
||||||
if time.Now().Unix() >= lockTime || batch != roomView.Room.PrevBatch {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
msgView := roomView.MessageView()
|
||||||
|
|
||||||
|
if !atomic.CompareAndSwapInt32(&msgView.loadingMessages, 0, 1) {
|
||||||
|
// Locked
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer atomic.StoreInt32(&msgView.loadingMessages, 0)
|
||||||
|
|
||||||
history, err := view.matrix.GetHistory(roomView.Room, 50)
|
history, err := view.matrix.GetHistory(roomView.Room, 50)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user