1
0
mirror of https://github.com/spacebarchat/client.git synced 2024-11-24 19:32:34 +01:00

implement new message list

fetch more is currently broken
This commit is contained in:
Puyodead1 2024-06-26 11:39:44 -04:00
parent 180c34e5f0
commit e20967d0f2
No known key found for this signature in database
GPG Key ID: A4FA4FEC0DD353FC
7 changed files with 213 additions and 141 deletions

View File

@ -52,7 +52,6 @@
"react-dom": "^18.2.0",
"react-fps-stats": "^0.3.1",
"react-hook-form": "^7.51.3",
"react-infinite-scroll-component": "^6.1.0",
"react-loading-skeleton": "^3.4.0",
"react-markdown": "^9.0.1",
"react-measure": "^2.5.2",
@ -71,6 +70,7 @@
"reoverlay": "^1.0.3",
"styled-components": "5.3.11",
"use-resize-observer": "^9.1.0",
"virtua": "^0.33.1",
"yup": "^1.4.0"
},
"devDependencies": {

View File

@ -149,9 +149,6 @@ dependencies:
react-hook-form:
specifier: ^7.51.3
version: 7.51.3(react@18.2.0)
react-infinite-scroll-component:
specifier: ^6.1.0
version: 6.1.0(react@18.2.0)
react-loading-skeleton:
specifier: ^3.4.0
version: 3.4.0(react@18.2.0)
@ -206,6 +203,9 @@ dependencies:
use-resize-observer:
specifier: ^9.1.0
version: 9.1.0(react-dom@18.2.0)(react@18.2.0)
virtua:
specifier: ^0.33.1
version: 0.33.1(react-dom@18.2.0)(react@18.2.0)
yup:
specifier: ^1.4.0
version: 1.4.0
@ -5504,7 +5504,7 @@ packages:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
get-intrinsic: 1.2.4
is-string: 1.0.7
dev: true
@ -5520,7 +5520,7 @@ packages:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
es-array-method-boxes-properly: 1.0.0
is-string: 1.0.7
dev: true
@ -5531,7 +5531,7 @@ packages:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
es-errors: 1.3.0
es-shim-unscopables: 1.0.2
dev: true
@ -5542,7 +5542,7 @@ packages:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
es-shim-unscopables: 1.0.2
dev: true
@ -5552,7 +5552,7 @@ packages:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
es-shim-unscopables: 1.0.2
dev: true
@ -5562,7 +5562,7 @@ packages:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
es-array-method-boxes-properly: 1.0.0
is-string: 1.0.7
dev: true
@ -5572,7 +5572,7 @@ packages:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
es-errors: 1.3.0
es-shim-unscopables: 1.0.2
dev: true
@ -5584,7 +5584,7 @@ packages:
array-buffer-byte-length: 1.0.1
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
es-errors: 1.3.0
get-intrinsic: 1.2.4
is-array-buffer: 3.0.4
@ -6838,6 +6838,33 @@ packages:
whatwg-mimetype: 2.3.0
whatwg-url: 8.7.0
/data-view-buffer@1.0.1:
resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.7
es-errors: 1.3.0
is-data-view: 1.0.1
dev: true
/data-view-byte-length@1.0.1:
resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.7
es-errors: 1.3.0
is-data-view: 1.0.1
dev: true
/data-view-byte-offset@1.0.0:
resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.7
es-errors: 1.3.0
is-data-view: 1.0.1
dev: true
/dayjs@1.11.10:
resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==}
dev: false
@ -7233,16 +7260,20 @@ packages:
escape-html: 1.0.3
dev: false
/es-abstract@1.22.4:
resolution: {integrity: sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg==}
/es-abstract@1.23.3:
resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==}
engines: {node: '>= 0.4'}
dependencies:
array-buffer-byte-length: 1.0.1
arraybuffer.prototype.slice: 1.0.3
available-typed-arrays: 1.0.7
call-bind: 1.0.7
data-view-buffer: 1.0.1
data-view-byte-length: 1.0.1
data-view-byte-offset: 1.0.0
es-define-property: 1.0.0
es-errors: 1.3.0
es-object-atoms: 1.0.0
es-set-tostringtag: 2.0.3
es-to-primitive: 1.2.1
function.prototype.name: 1.1.6
@ -7253,10 +7284,11 @@ packages:
has-property-descriptors: 1.0.2
has-proto: 1.0.3
has-symbols: 1.0.3
hasown: 2.0.1
hasown: 2.0.2
internal-slot: 1.0.7
is-array-buffer: 3.0.4
is-callable: 1.2.7
is-data-view: 1.0.1
is-negative-zero: 2.0.3
is-regex: 1.1.4
is-shared-array-buffer: 1.0.3
@ -7267,17 +7299,17 @@ packages:
object-keys: 1.1.1
object.assign: 4.1.5
regexp.prototype.flags: 1.5.2
safe-array-concat: 1.1.0
safe-array-concat: 1.1.2
safe-regex-test: 1.0.3
string.prototype.trim: 1.2.8
string.prototype.trimend: 1.0.7
string.prototype.trimstart: 1.0.7
string.prototype.trim: 1.2.9
string.prototype.trimend: 1.0.8
string.prototype.trimstart: 1.0.8
typed-array-buffer: 1.0.2
typed-array-byte-length: 1.0.1
typed-array-byte-offset: 1.0.2
typed-array-length: 1.0.5
typed-array-length: 1.0.6
unbox-primitive: 1.0.2
which-typed-array: 1.1.14
which-typed-array: 1.1.15
dev: true
/es-array-method-boxes-properly@1.0.0:
@ -7303,7 +7335,7 @@ packages:
asynciterator.prototype: 1.0.0
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
es-errors: 1.3.0
es-set-tostringtag: 2.0.3
function-bind: 1.1.2
@ -7314,26 +7346,33 @@ packages:
has-symbols: 1.0.3
internal-slot: 1.0.7
iterator.prototype: 1.1.2
safe-array-concat: 1.1.0
safe-array-concat: 1.1.2
dev: true
/es-module-lexer@1.4.1:
resolution: {integrity: sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==}
dev: true
/es-object-atoms@1.0.0:
resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==}
engines: {node: '>= 0.4'}
dependencies:
es-errors: 1.3.0
dev: true
/es-set-tostringtag@2.0.3:
resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==}
engines: {node: '>= 0.4'}
dependencies:
get-intrinsic: 1.2.4
has-tostringtag: 1.0.2
hasown: 2.0.1
hasown: 2.0.2
dev: true
/es-shim-unscopables@1.0.2:
resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==}
dependencies:
hasown: 2.0.1
hasown: 2.0.2
dev: true
/es-to-primitive@1.2.1:
@ -7721,7 +7760,7 @@ packages:
eslint: 8.57.0
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0)
hasown: 2.0.1
hasown: 2.0.2
is-core-module: 2.13.1
is-glob: 4.0.3
minimatch: 3.1.2
@ -7775,7 +7814,7 @@ packages:
emoji-regex: 9.2.2
es-iterator-helpers: 1.0.17
eslint: 8.57.0
hasown: 2.0.1
hasown: 2.0.2
jsx-ast-utils: 3.3.5
language-tags: 1.0.9
minimatch: 3.1.2
@ -8440,7 +8479,7 @@ packages:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
functions-have-names: 1.2.3
dev: true
@ -8464,7 +8503,7 @@ packages:
function-bind: 1.1.2
has-proto: 1.0.3
has-symbols: 1.0.3
hasown: 2.0.1
hasown: 2.0.2
dev: true
/get-node-dimensions@1.2.1:
@ -8646,6 +8685,13 @@ packages:
dependencies:
function-bind: 1.1.2
/hasown@2.0.2:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
dependencies:
function-bind: 1.1.2
dev: true
/hast-util-parse-selector@2.2.5:
resolution: {integrity: sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==}
dev: false
@ -9015,7 +9061,7 @@ packages:
engines: {node: '>= 0.4'}
dependencies:
es-errors: 1.3.0
hasown: 2.0.1
hasown: 2.0.2
side-channel: 1.0.5
dev: true
@ -9116,6 +9162,13 @@ packages:
dependencies:
hasown: 2.0.1
/is-data-view@1.0.1:
resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==}
engines: {node: '>= 0.4'}
dependencies:
is-typed-array: 1.1.13
dev: true
/is-date-object@1.0.5:
resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
engines: {node: '>= 0.4'}
@ -9312,7 +9365,7 @@ packages:
resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==}
engines: {node: '>= 0.4'}
dependencies:
which-typed-array: 1.1.14
which-typed-array: 1.1.15
dev: true
/is-typedarray@1.0.0:
@ -11523,7 +11576,7 @@ packages:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
dev: true
/object.fromentries@2.0.7:
@ -11532,7 +11585,7 @@ packages:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
dev: true
/object.getownpropertydescriptors@2.1.7:
@ -11542,8 +11595,8 @@ packages:
array.prototype.reduce: 1.0.6
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
safe-array-concat: 1.1.0
es-abstract: 1.23.3
safe-array-concat: 1.1.2
dev: true
/object.groupby@1.0.2:
@ -11552,7 +11605,7 @@ packages:
array.prototype.filter: 1.0.3
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
es-errors: 1.3.0
dev: true
@ -11560,7 +11613,7 @@ packages:
resolution: {integrity: sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==}
dependencies:
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
dev: true
/object.values@1.1.7:
@ -11569,7 +11622,7 @@ packages:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
dev: true
/obuf@1.1.2:
@ -12999,15 +13052,6 @@ packages:
react: 18.2.0
dev: false
/react-infinite-scroll-component@6.1.0(react@18.2.0):
resolution: {integrity: sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==}
peerDependencies:
react: '>=16.0.0'
dependencies:
react: 18.2.0
throttle-debounce: 2.3.0
dev: false
/react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
@ -13523,7 +13567,7 @@ packages:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
es-errors: 1.3.0
get-intrinsic: 1.2.4
globalthis: 1.0.3
@ -13826,8 +13870,8 @@ packages:
dependencies:
queue-microtask: 1.2.3
/safe-array-concat@1.1.0:
resolution: {integrity: sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==}
/safe-array-concat@1.1.2:
resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==}
engines: {node: '>=0.4'}
dependencies:
call-bind: 1.0.7
@ -14323,7 +14367,7 @@ packages:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
get-intrinsic: 1.2.4
has-symbols: 1.0.3
internal-slot: 1.0.7
@ -14332,29 +14376,31 @@ packages:
side-channel: 1.0.5
dev: true
/string.prototype.trim@1.2.8:
resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==}
/string.prototype.trim@1.2.9:
resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
es-object-atoms: 1.0.0
dev: true
/string.prototype.trimend@1.0.7:
resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==}
/string.prototype.trimend@1.0.8:
resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==}
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-object-atoms: 1.0.0
dev: true
/string.prototype.trimstart@1.0.7:
resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==}
/string.prototype.trimstart@1.0.8:
resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.22.4
es-object-atoms: 1.0.0
dev: true
/string_decoder@1.1.1:
@ -14745,11 +14791,6 @@ packages:
/throat@6.0.2:
resolution: {integrity: sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==}
/throttle-debounce@2.3.0:
resolution: {integrity: sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==}
engines: {node: '>=8'}
dev: false
/through2@2.0.5:
resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==}
dependencies:
@ -14991,8 +15032,8 @@ packages:
is-typed-array: 1.1.13
dev: true
/typed-array-length@1.0.5:
resolution: {integrity: sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==}
/typed-array-length@1.0.6:
resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.7
@ -15187,7 +15228,7 @@ packages:
resolution: {integrity: sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==}
dependencies:
define-properties: 1.2.1
es-abstract: 1.22.4
es-abstract: 1.23.3
has-symbols: 1.0.3
object.getownpropertydescriptors: 2.1.7
dev: true
@ -15236,6 +15277,30 @@ packages:
vfile-message: 4.0.2
dev: false
/virtua@0.33.1(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-xOzF5J+4KN12w1k7rNbocxjLYrWmGP2gXEDXqcHz7zWkf2vrCrsP/N3M/m3RhME/f/bNc5X22cvpIPqQeOP2MA==}
peerDependencies:
react: '>=16.14.0'
react-dom: '>=16.14.0'
solid-js: '>=1.0'
svelte: '>=4.0'
vue: '>=3.2'
peerDependenciesMeta:
react:
optional: true
react-dom:
optional: true
solid-js:
optional: true
svelte:
optional: true
vue:
optional: true
dependencies:
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/vite-plugin-chunk-split@0.5.0(vite@5.2.7):
resolution: {integrity: sha512-pasNKLhH+ICjoCF6HoKKvgmZ1LEPSCIKAa8Lz0ZpMyQC9bLmCLT7UxgKMULewsc9SUw89OX0udsGiIQCtr8wLA==}
peerDependencies:
@ -15640,7 +15705,7 @@ packages:
isarray: 2.0.5
which-boxed-primitive: 1.0.2
which-collection: 1.0.1
which-typed-array: 1.1.14
which-typed-array: 1.1.15
dev: true
/which-collection@1.0.1:
@ -15656,8 +15721,8 @@ packages:
resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
dev: false
/which-typed-array@1.1.14:
resolution: {integrity: sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==}
/which-typed-array@1.1.15:
resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==}
engines: {node: '>= 0.4'}
dependencies:
available-typed-arrays: 1.0.7

View File

@ -12,6 +12,7 @@ const Wrapper = styled(Container)<{ size: number; hasClick?: boolean }>`
background-color: transparent;
display: flex;
flex-direction: column;
user-select: none;
`;
interface Props {

View File

@ -13,7 +13,6 @@ import FloatingTrigger from "../floating/FloatingTrigger";
const Container = styled.div`
font-size: 16px;
font-weight: var(--font-weight-medium);
user-select: none;
&:hover {
text-decoration: underline;

View File

@ -1,9 +1,9 @@
import { observer } from "mobx-react-lite";
import React from "react";
import InfiniteScroll from "react-infinite-scroll-component";
import PulseLoader from "react-spinners/PulseLoader";
import React, { useEffect, useRef, useState } from "react";
import { PulseLoader } from "react-spinners";
import styled from "styled-components";
import useResizeObserver from "use-resize-observer";
import { VList, VListHandle } from "virtua";
import useLogger from "../../hooks/useLogger";
import { useAppStore } from "../../stores/AppStore";
import { MessageGroup as MessageGroupType } from "../../stores/MessageStore";
@ -17,34 +17,73 @@ export const MessageAreaWidthContext = React.createContext(0);
export const MESSAGE_AREA_PADDING = 82;
const Container = styled.div`
flex: 1 1 auto;
overflow-y: auto;
display: flex;
flex-direction: column-reverse;
flex: 1;
`;
const EndMessageContainer = styled.div`
margin: 16px 16px 0 16px;
`;
const Spacer = styled.div`
height: 20px;
`;
interface Props {
guild: Guild;
channel: Channel;
before?: string;
}
/**
* Main component for rendering the messages list of a channel
*/
function MessageList({ guild, channel }: Props) {
function MessageList({ guild, channel, before }: Props) {
const app = useAppStore();
const logger = useLogger("MessageList.tsx");
const [hasMore, setHasMore] = React.useState(true);
const [canView, setCanView] = React.useState(false);
const [hasMore, setHasMore] = useState(true);
const [canView, setCanView] = useState(false);
const [loading, setLoading] = useState(false);
const messageGroups = channel.messages.groups;
const ref = React.useRef<HTMLDivElement>(null);
const { width } = useResizeObserver<HTMLDivElement>({ ref });
const wrapperRef = useRef<HTMLDivElement>(null);
const { width } = useResizeObserver<HTMLDivElement>({ ref: wrapperRef });
const ref = useRef<VListHandle>(null);
React.useEffect(() => {
useEffect(() => {
ref.current?.scrollToIndex(
messageGroups.reduce((p, c) => p + c.messages.length, 0) +
1 /* +1 to account for the spacer that adds some margin to the bottom */,
);
}, [messageGroups]);
const fetchMore = React.useCallback(() => {
setLoading(true);
if (!channel.messages.count) {
logger.warn("channel has no messages, aborting!");
setLoading(false);
return;
}
// get last group
const lastGroup = messageGroups[messageGroups.length - 1];
if (!lastGroup) {
logger.warn("No last group found, aborting fetchMore");
setLoading(false);
return;
}
// ignore queued messages
if ("status" in lastGroup.messages[0]) return;
// get first message in the group to use as before
const before = lastGroup.messages[0].id;
logger.debug(`Fetching 50 messages before ${before} for channel ${channel.id}`);
channel.getMessages(app, false, 50, before).then((r) => {
if (r < 50) {
setHasMore(false);
}
});
setLoading(false);
}, [channel, messageGroups]);
useEffect(() => {
const permission = Permissions.getPermission(app.account!.id, guild, channel);
const hasPermission = permission.has("READ_MESSAGE_HISTORY");
setCanView(hasPermission);
@ -55,7 +94,7 @@ function MessageList({ guild, channel }: Props) {
}
if (guild && channel && channel.messages.count === 0) {
channel.getMessages(app, true).then((r) => {
channel.getMessages(app, true, 50, before).then((r) => {
if (r < 50) {
setHasMore(false);
}
@ -69,29 +108,6 @@ function MessageList({ guild, channel }: Props) {
};
}, [guild, channel]);
const fetchMore = React.useCallback(() => {
if (!channel.messages.count) {
logger.warn("channel has no messages, aborting!");
return;
}
// get last group
const lastGroup = messageGroups[messageGroups.length - 1];
if (!lastGroup) {
logger.warn("No last group found, aborting fetchMore");
return;
}
// ignore queued messages
if ("status" in lastGroup.messages[0]) return;
// get first message in the group to use as before
const before = lastGroup.messages[0].id;
logger.debug(`Fetching 50 messages before ${before} for channel ${channel.id}`);
channel.getMessages(app, false, 50, before).then((r) => {
if (r < 50) {
setHasMore(false);
}
});
}, [channel, messageGroups]);
const renderGroup = React.useCallback(
(group: MessageGroupType) => (
<MessageGroup key={`messageGroup-${group.messages[group.messages.length - 1].id}`} group={group} />
@ -101,20 +117,25 @@ function MessageList({ guild, channel }: Props) {
return (
<MessageAreaWidthContext.Provider value={(width ?? 0) - MESSAGE_AREA_PADDING}>
<Container id="scrollable-div" ref={ref}>
<Container>
{canView ? (
<InfiniteScroll
dataLength={messageGroups.length}
next={fetchMore}
<VList
ref={ref}
style={{
display: "flex",
flexDirection: "column-reverse",
marginBottom: 30,
overflow: "hidden",
}} // to put endMessage and loader to the top.
hasMore={hasMore}
inverse={true}
loader={
flex: 1,
}}
reverse
>
{((messageGroups.length === 0 && !loading) || (!loading && !hasMore)) && (
<EndMessageContainer>
<h1 style={{ fontWeight: 700, margin: "8px 0" }}>Welcome to #{channel.name}!</h1>
<p style={{ color: "var(--text-secondary)" }}>
This is the start of the #{channel.name} channel.
</p>
<HorizontalDivider />
</EndMessageContainer>
)}
{loading && (
<PulseLoader
style={{
display: "flex",
@ -124,22 +145,10 @@ function MessageList({ guild, channel }: Props) {
}}
color="var(--primary)"
/>
}
// FIXME: seems to be broken in react-infinite-scroll-component when using inverse
scrollThreshold={0.5}
scrollableTarget="scrollable-div"
endMessage={
<EndMessageContainer>
<h1 style={{ fontWeight: 700, margin: "8px 0" }}>Welcome to #{channel.name}!</h1>
<p style={{ color: "var(--text-secondary)" }}>
This is the start of the #{channel.name} channel.
</p>
<HorizontalDivider />
</EndMessageContainer>
}
>
{messageGroups.map((group) => renderGroup(group))}
</InfiniteScroll>
)}
{messageGroups.map((group, index) => renderGroup(group))}
<Spacer />
</VList>
) : (
<div
style={{

View File

@ -107,8 +107,7 @@ export default class MessageStore {
});
}
return groups;
}, [] as MessageGroup[])
.reverse();
}, [] as MessageGroup[]);
return sortedGroups;
}

View File

@ -3,7 +3,6 @@ import type {
APIChannel,
APIInvite,
APIOverwrite,
APIReadState,
APIUser,
APIWebhook,
GatewayVoiceState,
@ -53,7 +52,7 @@ export default class Channel {
@observable retentionPolicyId?: string;
@observable messages: MessageStore;
@observable voiceStates?: GatewayVoiceState[];
@observable readStates?: APIReadState[];
// @observable readStates?: APIReadState[]; ????? this seems wrong
@observable webhooks?: APIWebhook[];
@observable flags: number;
@observable defaultThreadRateLimitPerUser: number;
@ -89,7 +88,7 @@ export default class Channel {
this.invites = channel.invites;
this.retentionPolicyId = channel.retention_policy_id;
this.voiceStates = channel.voice_states;
this.readStates = channel.read_states;
// this.readStates = channel.read_states;
this.webhooks = channel.webhooks;
this.flags = channel.flags;
this.defaultThreadRateLimitPerUser = channel.default_thread_rate_limit_per_user;