551 Commits

Author SHA1 Message Date
trashtemp
4889830c06 feat(profile): added statistics to bot profile 2021-12-21 17:03:51 +01:00
trashtemp
8eabc47915 fix(profile): finished modal design 2021-12-21 13:26:47 +01:00
trashtemp
9ab7e5718f fix(profile): fixed status label alignment 2021-12-21 12:20:33 +01:00
Paul
3be5307340 chore: hide badge editor 2021-12-21 11:14:47 +00:00
Paul
256a9650b2 feat(profile): add "add to server" button for bots 2021-12-21 10:44:14 +00:00
Paul
9415c2b5d8 chore(settings): add dummy element for index 2021-12-20 21:07:20 +00:00
Paul Makles
6e4c4f3ae2 fix(ui): fixes for mobile UI, settings and sessions pages (#451)
Co-authored-by: trashtemp <96388163+trashtemp@users.noreply.github.com>
2021-12-20 20:48:37 +00:00
Paul Makles
e7459790c5 chore(ci): bump Docker image to node v16 2021-12-20 20:48:27 +00:00
trashtemp
27bc4e74b9 fix: fixed channel sidebar on mobile 2021-12-20 14:56:37 +01:00
Paul Makles
9298f205fc feat(settings): UI improvements (#448)
* Fixed CSS for Settings.tsx + new Theme Shop design

* reformat

* More changes to UI CSS

* Small CSS fixes for Settings.tsx, Account, Bots

* Updated theme shop, settings pages, cleanup

* chore: force sync language submodule

* fix(sidebar): prevent items from shrinking

* fix(push): fix timestamp and icon for push notifications

* fix(voice): hide grant permission button after grant

* chore: hide new shop / chevron before merge

* chore(ci): bump node to v16 in dockerfile

* fix(sidebar): change width of channel sidebar

Co-authored-by: trashtemp <96388163+trashtemp@users.noreply.github.com>
2021-12-20 13:37:21 +00:00
Ed L
535a40df0c fix: make the autocompletor actually run when editing messages (#445) 2021-12-20 11:31:33 +00:00
David Roth
91f6947634 fix(docker): fix vite-plugin-pwa failing on build #416 (#443) 2021-12-11 19:42:03 +00:00
Paul Makles
3a093018eb feat(i18n): add 3 languages 2021-12-07 16:44:17 +00:00
Ed L
d8f48743b3 fix: make the category name input use --font (#413) 2021-11-22 22:13:48 +00:00
Paul
657e9eb04e feat(push): read URL from notification
also matches fix on delta, closes #410
2021-11-20 12:53:35 +00:00
Paul
6748ec9295 chore: bump vite to 2.6.14 2021-11-20 11:55:05 +00:00
An00nymushun
1983155486 fix(ui): flicker on modal close (#407) 2021-11-18 20:36:24 +00:00
Paul
e5a11a2f1e fix: prevent overscroll
fixes #367
2021-11-14 23:02:51 +00:00
Paul
67834309b1 fix: use masquerade everywhere applicable
fixes #400
2021-11-14 19:53:50 +00:00
Paul
fb1de01edd fix: remove removed messages from reply bar
fixes #71
fixes #143
2021-11-14 19:30:41 +00:00
Paul
74e786053e fix: scroll to top in settings
fixes #108
2021-11-14 19:18:37 +00:00
Paul
b2a222d7e8 fix: prevent native settings being opened on non-native
fixes #344
2021-11-14 18:51:19 +00:00
Paul
b938f6620b fix: prevent reply overflow
fixes #399
2021-11-14 18:46:46 +00:00
Paul
374f5d1747 fix: accent buttons and allow selection of back
fixes #398
fixes #397
2021-11-14 18:29:46 +00:00
Ed L
94fb1c6d71 fix: censor the whole email (#374) 2021-11-14 14:26:35 +00:00
Paul
8664cda744 feat: add moderation badge 2021-11-13 23:11:40 +00:00
Paul
f467349083 feat: add new badges 2021-11-13 22:55:41 +00:00
Ed L
50e1aa0dff feat: add delete server button to server settings (#373)
Co-authored-by: Paul Makles <paulmakles@gmail.com>
2021-11-12 22:24:30 +00:00
tbodt
31d90481c2 chore: rename the string for previewing the profile page (#390) 2021-11-12 22:21:35 +00:00
Steveplays
bef24b7cdd fix: added hover event to overline + removed context menu (#393) 2021-11-12 20:20:50 +00:00
insertish
594693f8d7 ci: Synced local '.github/workflows/triage_pr.yml' with remote 'workflows/triage_pr.yml' 2021-11-11 20:08:36 +00:00
insertish
11b164c3f5 ci: Created local '.github/workflows/triage_pr.yml' from remote 'workflows/triage_pr.yml' 2021-11-11 19:09:01 +00:00
insertish
8a2e36ffb4 ci: Synced local '.github/workflows/triage_issue.yml' with remote 'workflows/triage_issue.yml' 2021-11-11 19:01:54 +00:00
Paul Makles
931dc4b693 ci: update global workflows (#392)
Co-authored-by: web-flow <noreply@github.com>
2021-11-11 18:35:11 +00:00
Paul Makles
5b6c1050ad chore: add quick start instructions 2021-11-11 16:41:55 +00:00
Paul
3cf8c64d7c fix(markdown): enable linkify, disable fuzzyLink 2021-11-04 21:04:44 +00:00
Paul
d82573b5fc feat(messaging): render masqueraded messages 2021-11-04 20:55:26 +00:00
Paul
7e7f9d0f23 chore(markdown): disable linkify 2021-11-04 14:35:41 +00:00
Paul
112a6f5497 fix(markdown): fix line breaks
fixes #214
2021-11-04 14:33:59 +00:00
Paul
20590641bc fix(sidebar): handle channel as muted if 'none' 2021-11-04 13:42:46 +00:00
Paul
3d5df68771 chore: bump languages and generate yarn.lock 2021-10-31 22:47:50 +00:00
Ed L
893cd6b4cc feat(i18n): translate home buttons and server tooltips (#361) 2021-10-31 22:42:40 +00:00
bree
1800aace43 feat: require at least two characters to autocomplete emoji (#298) 2021-10-31 22:36:38 +00:00
David Epely
3ef3f84877 fix(settings): close microphone access navigating away from page (#219)
Co-authored-by: Paul Makles <paulmakles@gmail.com>
2021-10-31 21:52:20 +00:00
appare
d5c8749b80 feat(settings): prompt for audio access from button (#263) 2021-10-31 21:40:04 +00:00
3nt3
b09ccd90ba fix: add context menu to individual attachments if > 1 attached (#348) 2021-10-31 21:25:33 +00:00
megumin
aa13e9d96f fix: Correct grammar in bot invite screen (#237) 2021-10-31 21:12:26 +00:00
RigidStudios
856bbb598c fix: muted channels no longer have new messages badge (#297) 2021-10-31 21:10:42 +00:00
Sirawit Thaya
e12869fbe4 feat: Theme shop link on appearance rewrites history
#245
2021-10-31 21:07:49 +00:00
o8z
eab5c299a8 feat(login): add more email providers (#363) 2021-10-31 18:17:12 +00:00
Marie
c4881db86c feat: handle nsfw flag & added monospace font (#258) 2021-10-31 17:57:35 +00:00
Paul Makles
3b843dbfad Merge pull request #296 from quuu/category_name_fix 2021-10-31 17:54:06 +00:00
Paul
cda1465f35 chore(languages): add Belarusian (be) to Revolt
#362
2021-10-31 17:44:49 +00:00
Paul
dafdf24300 chore(languages): Change Tamil flag.
Closes #352
2021-10-31 17:36:26 +00:00
Paul
ef05a5993c chore(submodule): pull in latest language changes 2021-10-31 16:48:23 +00:00
Paul Makles
92597ab1cd Merge pull request #360 from revoltchat/rework/categories-kanban 2021-10-31 16:38:10 +00:00
Paul
f97925073a feat(rbd): transform rbd types to Preact from React 2021-10-31 16:04:37 +00:00
Paul Makles
7ab8632bd0 Merge pull request #359 from 3nt3/master 2021-10-31 09:59:08 +00:00
Paul
c208064d2c feat(categories): include uncategorised channels; add category / channel; delete category 2021-10-30 19:38:18 +01:00
Paul
bb5509f660 feat(categories): autosave category changes 2021-10-30 18:20:12 +01:00
Paul Makles
ae2efcd9c6 Merge pull request #266 from brecert/fix-265 2021-10-30 15:55:34 +00:00
3nt3
d78640ed48 Merge branch 'master' of github.com:3nt3/revite 2021-10-30 04:20:30 +02:00
3nt3
81cd821601 Fix icloud address from mail.aol.com to mail.icloud.com
Fixes #325

Signed-off-by: 3nt3 <gott@3nt3.de>
2021-10-30 04:19:37 +02:00
Paul
da47348273 feat(categories): basic dnd kanban board 2021-10-27 23:25:08 +01:00
Paul Makles
314ecee95c Start implementing kanban view. 2021-10-27 20:28:26 +01:00
Paul
bcfc2336a4 fix(asset): wrong path specified for wideSVG 2021-10-23 16:57:07 +01:00
Paul
6e3905eb0f fix(asset): wideSVG is refusing to exist, use legacy loading mechanism 2021-10-23 16:42:04 +01:00
Paul
6595b7687a fix(assets): missed 1 space 2021-10-23 16:04:23 +01:00
Paul
d8f2cac171 feat(assets): pull specific branch for assets if specified 2021-10-23 16:00:20 +01:00
Paul
5e0c8e0444 fix(assets): remove duplicate, fix wideSVG 2021-10-23 15:48:35 +01:00
Paul
5603278071 chore(assets): create new default set of assets
feat(assets): prepare assets before build
2021-10-23 15:38:52 +01:00
Paul
195a9bda35 Fix(voice): Voice UI would not react to actions.
Feat(voice): Allow accessing user profile from voice UI.

Fixes #89. Fixes #91.
2021-10-20 22:39:26 +01:00
Paul
d6169f3c3a Consider channel overrides for perms, fixes #334. 2021-10-10 19:44:05 +01:00
Paul
4ec598db81 Hide edit profile button while editing, closes #301.
Block UI when account edit request is sent, closes #303.
2021-10-10 16:32:30 +01:00
Paul
89c0026fa2 Fix mark read logic, should fix #307.
Add bot delete confirmation, closes #302.
2021-10-10 16:28:56 +01:00
Paul
26277dc0ce Merge 220 commits for translations. 2021-10-10 16:14:08 +01:00
Paul
14e749b65b Mark link as trusted when opening, fixes #331. 2021-10-10 16:11:43 +01:00
Paul Makles
40d95025b5 Merge pull request #320 from Snazzah/patch-2 2021-10-10 15:06:14 +01:00
Paul Makles
148c0edcbf Merge pull request #268 from brecert/fix-198 2021-10-09 23:45:52 +01:00
Paul Makles
a04c68f5e8 Merge pull request #267 from brecert/fix-196 2021-10-09 23:44:36 +01:00
Paul Makles
90bd92e0ef Merge pull request #328 from f3rr31/patch-1 2021-10-09 23:08:39 +01:00
f3rr31
e996e0b25d Spelling error fix for Magyar at line #104
Changed Magyar to magyar at line #104. Magyar is magyar (small caps) in Hungarian; same as with Estonian (eesti) and Finnish (suomi).
2021-10-10 00:02:17 +02:00
Snazzah
b0d6d62371 Add HEY to mail providers 2021-10-02 22:55:50 -05:00
Paul Makles
6c2f76debc Remove conditional workflow run since it just doesn't work. 2021-09-30 10:47:24 +00:00
Paul Makles
22516992a6 Update mirroring.yml 2021-09-30 10:46:08 +00:00
Paul
920f78b650 Virtualise server settings user lists. Closes #300 2021-09-25 14:43:28 +01:00
Paul
81379d6ec4 Explicitly deny bad URLs.
Fixes #252.
Handle embed untrusted links better.
2021-09-25 10:54:32 +01:00
Paul Makles
66289911ba Merge pull request #294 from RigidStudios/fixroles 2021-09-24 15:39:04 +01:00
Paul Makles
4dda7f12db Merge pull request #215 from Snazzah/bots-token 2021-09-24 15:35:26 +01:00
Paul Makles
44b02fecb0 Merge pull request #260 from brecert/profile-fix 2021-09-24 15:34:45 +01:00
Paul Makles
8c23b309d9 Merge pull request #287 from RigidStudios/startnotes 2021-09-24 14:25:49 +01:00
Paul Makles
e9a88bc31c Merge pull request #278 from TaiAurori/master 2021-09-24 13:59:57 +01:00
Paul Makles
6407f3b924 Merge pull request #257 from brecert/no-send-composing 2021-09-24 13:16:57 +01:00
Andrew Qu
25bc0c1ea3 fixed name 2021-09-23 22:35:17 -07:00
RigidStudios
d1b686945a Revert "ConversationStart changed for notes/normal channel"
This reverts commit 74297085d7.
2021-09-23 23:11:38 +04:00
RigidStudios
7af2bce00e Revert "don't change onboarding on this pr"
This reverts commit 416cc0a991.
2021-09-23 23:11:33 +04:00
RigidStudios
8ac7403522 Prettier, Fix no role refresh 2021-09-23 23:08:28 +04:00
Paul Makles
db111bfc01 Merge pull request #262 from Mysterious-Dev/gitignore 2021-09-23 17:48:55 +01:00
Paul Makles
6e47863c7c Merge pull request #283 from RigidStudios/onboardinglb 2021-09-23 17:07:52 +01:00
RigidStudios
416cc0a991 don't change onboarding on this pr 2021-09-23 00:00:38 +04:00
RigidStudios
74297085d7 ConversationStart changed for notes/normal channel 2021-09-22 23:59:22 +04:00
RigidStudios
75704773af Add linebreak before logo 2021-09-22 18:04:45 +04:00
TaiAurori
21122583aa singular form of "members" when only one member 2021-09-21 14:41:57 -04:00
TaiAurori
f7f101f7b2 move imports 2021-09-21 14:13:41 -04:00
TaiAurori
3d5c7ab9ce invite embed tweaks 2021-09-21 14:02:38 -04:00
Paul
ce0749d9e8 Prevent double sending of requests. 2021-09-19 13:47:25 +01:00
brecert
ecb0bff4f3 Set appropriate autocomplete attributes for password reset
- make autocomplete set to `current-password` and `new-password` for password resets
- fixes #198
2021-09-19 04:11:54 -04:00
brecert
51092db01b Change UserHover to use global identity instead of server
- fixes #196
2021-09-19 03:42:01 -04:00
brecert
abe2e2db40 Fix send message related context menu options when unable to send messages
- fixes `reply` and `quote message` from appearing in the context menus for messages when unable to send messages.
- fixes #265
2021-09-19 00:47:01 -04:00
Mysterious_Dev
77249b7a25 Gitignore 2021-09-18 12:20:47 +02:00
brecert
945e072327 Fixes background not updating on profile
- fixes #110
2021-09-17 19:44:19 -04:00
Paul Makles
3b9916c072 Merge pull request #259 from brecert/theme-fix 2021-09-17 22:38:20 +01:00
brecert
63479737a8 Fix trying to in undefined for themes 2021-09-17 17:30:14 -04:00
brecert
5b16977b0e Fix enter key sending message while still composing 2021-09-17 17:20:22 -04:00
Paul Makles
2ff9c91287 Merge pull request #251 from brecert/actions-demo-test 2021-09-17 09:40:23 +01:00
Paul
51f23f5aa0 Include noreferrer on embed links / window.open. 2021-09-17 09:37:07 +01:00
brecert
f01eb1d70f Add commit messages 2021-09-16 16:38:18 -04:00
Paul
d5430a7920 Use server configuration for voso websocket. 2021-09-16 10:27:33 +01:00
Paul Makles
0494f0647a Create SECURITY.md 2021-09-15 16:49:13 +00:00
Paul
1614d7a739 Fix overflow on home tab. 2021-09-15 14:53:40 +01:00
Paul Makles
7d5911c96d Merge pull request #240 from nerrixDE/master 2021-09-15 14:48:55 +01:00
brecert
d123c5c44d Fix push issues for cleanup by removing single-commit
- note: in the future, `JamesIves/github-pages-deploy-action@4.1.5` may need to be replaced or supplemented by git commands to fully reset the preview branch so that images and builds do not linger and take up storage for too long
2021-09-14 19:21:55 -04:00
brecert
2e8c3aa242 Make BASE in cleanup relative 2021-09-14 18:58:57 -04:00
Snazzah
bf7fd14fb7 Use 5 dots 2021-09-14 17:54:17 -05:00
Paul
4b8ad44aa9 Fix unreads and mark as read. 2021-09-14 21:09:42 +01:00
Paul Makles
fc03336ea3 Merge pull request #225 from brecert/theme_shop
Fix theme shop themes not applying as a base
2021-09-14 20:39:28 +01:00
Nerrix
afbd513fb8 Link revolt.social for server & bot discovery 2021-09-14 19:06:34 +02:00
Paul
75ee61525f Bump revolt.js to include rate limiter.
Handle new server flags.
Show server ping in developer tab.
2021-09-14 17:18:44 +01:00
Paul Makles
ffb0443bf6 Merge pull request #208 from goaaats/feat/no_channels_design 2021-09-14 15:42:46 +01:00
Paul
857e6e4d54 Merge incoming translations. (103 commits) 2021-09-14 15:42:15 +01:00
Paul
cc45b9e255 Simplify how last message is handled. 2021-09-14 15:07:42 +01:00
brecert
ba2d0dd6d1 Fix wrong folder 2021-09-14 01:48:28 -04:00
brecert
44b1e2a079 Fix not cding into the folder 2021-09-14 01:37:37 -04:00
brecert
450789fafe Merge install and build together 2021-09-14 01:30:52 -04:00
brecert
785badae6e Fix env location 2021-09-14 01:16:31 -04:00
brecert
aaac315736 Fix shell not being included for build action 2021-09-14 01:10:57 -04:00
brecert
f554687878 Fix build being build_preview 2021-09-14 00:51:27 -04:00
brecert
f584819a16 Fix secret not needing to be interpolated 2021-09-14 00:44:46 -04:00
brecert
628bf52ff3 Use ignored paths for pull_request events as well 2021-09-14 00:27:30 -04:00
brecert
cdf900d08b Change docker workflow to exclude preview workflows
- changed the docker workflow to exclude preview workflows from causing the docker workflow to run again
2021-09-14 00:26:18 -04:00
brecert
951a773b2c Change mirror to only run if a key is set 2021-09-14 00:22:16 -04:00
brecert
12547ba0fe Improve preview cleanup interpolation 2021-09-14 00:03:58 -04:00
brecert
f28fd40a78 Add support for external repositories with pull request previews 2021-09-13 23:54:39 -04:00
Paul
45c7cd0307 Fix inaccessible invite page / reset page / verify page when logged in. 2021-09-13 17:22:17 +01:00
Paul
52875ab197 Fix change email / password. 2021-09-13 16:41:47 +01:00
Paul Makles
8da6f87efb Merge pull request #216 from gregorypappas/dominant-baseline 2021-09-12 00:28:23 +01:00
Paul Makles
60c3a5ba11 Merge pull request #223 from brecert/identity-fix
Improve server identity avatar preview
2021-09-11 23:53:17 +01:00
Paul Makles
4c5504cea8 Merge pull request #224 from brecert/misc-fixes 2021-09-11 23:52:15 +01:00
Paul Makles
d09de028b3 Merge pull request #222 from brecert/actions-demo 2021-09-11 23:51:28 +01:00
brecert
537f9b1596 Fix theme shop themes not applying as a base
- [#217] fixed theme shop themes not applying as a base
- added `themes` state path to store themes locally at
2021-09-11 15:40:14 -04:00
Paul
5b422b89e3 Migrate to rAuth v1. 2021-09-11 17:36:23 +01:00
brecert
806e3108cb Improve reply mention styling
- [#220] reply mention now uses translations
- reply mention styling improved
  - `@` fits better
  - `min-width: 6ch` is used to remove shifting between `on` and `off` lengths, mostly for the english `on/off` but could be modified to work with any language in the future.
2021-09-11 11:53:50 -04:00
brecert
33d79beae6 Improve server identity avatar preview
- server identity avatar preview now displays your current avatar, but desaturated and grayscale when no avatar is set

resolves #218
2021-09-11 11:38:58 -04:00
brecert
4a5d78d909 Use single-commit for build-previews 2021-09-11 10:12:14 -04:00
brecert
9bd31c4c7e Use base url for building actions 2021-09-10 18:03:06 -04:00
brecert
08e226cd0c Disable yarn check temporarily 2021-09-10 14:59:37 -04:00
brecert
28df14b734 Add pull request preview actions 2021-09-10 14:48:48 -04:00
Gregory Pappas
ee97e9bc0f FIx ping counter alignment in Firefox but actually
This property isn't transformed into kebab-case due to a bug in Preact.
2021-09-10 06:52:05 -05:00
Snazzah
5f68a5c831 Remove bots token dots 2021-09-10 05:09:26 +00:00
Paul
a4138b52b0 Update translations. 2021-09-09 23:19:20 +01:00
Paul
0daaeef9d4 Update Typescript to 4.4.2.
Fix issues associated with new version.
2021-09-09 23:02:47 +01:00
Paul Makles
7bd6348e9d Merge pull request #211 from iamdey/fix_settings_audio 2021-09-09 22:56:53 +01:00
Paul
4f8cae961b Bump revolt-api 2021-09-09 22:55:02 +01:00
Paul Makles
633933fb48 Merge pull request #203 from goaaats/fix/youtube_timestamp
Append youtube timestamp to embed url if provided by january
2021-09-09 22:53:36 +01:00
Paul
048267b419 Remove stray console.log and update translations.
Update themes endpoint and filter unmatched commits.
2021-09-09 22:39:17 +01:00
Paul Makles
efbbb6f1aa Merge pull request #199 from brecert/mentions-methods 2021-09-09 22:00:03 +01:00
Paul Makles
99116981ab Merge pull request #188 from brecert/theme_shop 2021-09-09 21:58:13 +01:00
Paul Makles
0acfd23334 Merge pull request #190 from leodr/settings-category-alignment
Add padding to settings category titles to align the visually with icons
2021-09-09 21:08:13 +01:00
Paul Makles
d7e245ba58 Merge pull request #192 from goaaats/fix/filter_alt_lang
Filter "alt" languages when selecting based on navigator
2021-09-09 21:07:50 +01:00
Paul Makles
9b4f91dde5 Merge pull request #194 from gregorypappas/patch-1
Fix ping count alignment in Firefox
2021-09-09 21:07:40 +01:00
Paul Makles
f4b54c2f64 Merge pull request #210 from goaaats/fix/empty_invite_redirect 2021-09-09 21:06:27 +01:00
Paul Makles
2b3ff50b33 Merge pull request #178 from Snazzah/patch-1 2021-09-09 21:04:58 +01:00
Paul Makles
6930e0eb40 Merge pull request #180 from Snazzah/invite-count 2021-09-09 21:04:43 +01:00
Paul Makles
c38bd702b7 Merge pull request #184 from Rexogamer/master 2021-09-09 21:04:26 +01:00
Paul Makles
3c487cd2a6 Merge pull request #185 from zaxutic/monospace-font 2021-09-09 21:04:05 +01:00
Paul Makles
da7a27f325 Merge pull request #179 from Snazzah/server-identity-revamp 2021-09-09 21:03:43 +01:00
Paul Makles
ee1f37abbc Merge pull request #189 from AirTMZ/patch-1
Update Locale.tsx language selection from Japan -> Japanese
2021-09-09 21:03:03 +01:00
Paul Makles
01b6c292ee Merge pull request #202 from brecert/hide-channels 2021-09-09 20:55:41 +01:00
Paul Makles
f925479121 Merge pull request #206 from goaaats/fix/default_channel 2021-09-09 20:53:15 +01:00
Paul Makles
932756d7c7 Merge pull request #204 from Snazzah/bots-banner-and-info
Add banner and info box to bots page
2021-09-09 20:49:54 +01:00
Paul Makles
4bf3140f22 Merge pull request #209 from brecert/image-fixes 2021-09-09 20:43:26 +01:00
Paul Makles
5f233249ef Merge pull request #181 from Snazzah/samsung-icon-session 2021-09-09 20:35:32 +01:00
David Epely
cd7c612058 [settings][audio] fix labels of microphone selection
- ask user for microphone permission (prompt).
- handle error when permission is blocked.
- Suggest retry if the permission is still not set and no prompt.
2021-09-08 22:57:13 +02:00
goat
8185b59771 fix: redirect to / on empty invites 2021-09-08 19:35:53 +02:00
brecert
999fc5b639 Fix major image bugs for chrome 93+
- fixed major bugs for chrome 93+ at the cost of minor issues that may appear (unsure, did not find any in testing)
- position scaled image to the left for firefox (firefox aspect-ratio still does not scale correctly)
- added `--width` and `--height` to the `Grid` for theme creators who may want to use such information easily
2021-09-08 07:01:11 -04:00
Snazzah
0dfeb7b421 Merge remote-tracking branch 'origin' into samsung-icon-session 2021-09-08 08:42:26 +00:00
goat
87d1391e1b feat: add channel placeholder 2021-09-08 02:40:57 +02:00
goat
3b77628f9f feat: use channel component for server route 2021-09-08 02:36:31 +02:00
goat
a32a7d409f remove unused import 2021-09-07 21:42:32 +02:00
goat
55a7b00954 fix: choose the first channel in the server if none is selected 2021-09-07 21:40:46 +02:00
Snazzah
b9330f559c Add banner and info box to bots page 2021-09-07 17:51:44 +00:00
goat
64f1cc5e4a fix: append youtube timestamp to embed url if provided by january 2021-09-07 17:36:33 +02:00
brecert
04158302ac Remove the ability to hide the channel sidebar on mobile 2021-09-07 10:57:40 -04:00
brecert
ed56967e10 Add the ability to hide the channel sidebar
(the left one)
2021-09-07 10:51:46 -04:00
brecert
f35ebeab67 Add shift+click to channel links 2021-09-07 09:26:12 -04:00
brecert
a308e6ecb8 Add shift+click to mention mentions 2021-09-07 09:09:12 -04:00
brecert
b166b06321 Change mention to channel mention 2021-09-07 08:58:39 -04:00
brecert
dd9b486dab Add shift+click to link to a channel in the textarea 2021-09-07 08:34:40 -04:00
brecert
2966e77917 Add shift+click to mention a user in the textarea 2021-09-07 08:14:22 -04:00
brecert
28b2d8dcab Improve accessibility and styling of theme shop 2021-09-07 06:31:49 -04:00
brecert
068540d366 Make theme shop hidden an experiment 2021-09-07 05:27:51 -04:00
Gregory Pappas
00d4d975cf Fix ping count alignment in Firefox 2021-09-07 02:13:15 -05:00
brecert
d7f08449cb Minor style improvements 2021-09-07 02:47:12 -04:00
goat
ef1a6a4454 fix: filter alt langs when selecting by navigator 2021-09-07 01:31:16 +02:00
Leo Driesch
c520fbf59a Add padding to settings category titles to align the visually with icons 2021-09-06 20:26:15 +02:00
AirTMZ
d6b3456129 Update Locale.tsx 2021-09-06 16:10:11 +01:00
brecert
6a32e451ac Use VITE_THEMES_URL for the default theme manifest
- typed `ImportMeta` to have `env`
2021-09-06 06:38:53 -04:00
brecert
6d85c9b725 Add under construction warning for the theme shop 2021-09-06 06:24:01 -04:00
brecert
414dcd51c0 Add base theme shop implementation and pane
- added theme shop settings pane
- added `generateVariables` for themes
- added `preview.svg` for previewing themes until a proper solution is made
2021-09-06 06:02:30 -04:00
Michael Vo
8603a390c0 Use monospace font for Theme Overrides code section 2021-09-05 16:16:20 +10:00
Ed L
46831314d1 add tooltip/help icon for bot id 2021-09-04 23:34:44 +01:00
Paul
4787a2166f Update submodule origin. 2021-09-04 22:50:03 +01:00
Snazzah
20bcc96ab3 Add Samsung Browser Icon to Sessions 2021-09-04 14:59:56 +00:00
Paul
bd3678f515 Add Enchantment Table. 2021-09-04 15:50:58 +01:00
Paul
eea13a30b8 Fix .env.build values. 2021-09-03 22:59:04 +01:00
Paul
fc633ee017 All need to include sirv-cli. 2021-09-03 21:36:18 +01:00
Snazzah
2b84850891 Format member count in invites 2021-09-03 18:34:16 +00:00
Paul
2c27044900 Fix Docker builds. 2021-09-03 19:27:39 +01:00
Snazzah
b0407490a8 Add translate strings to server identity 2021-09-03 17:45:10 +00:00
Snazzah
11f8d081ba Revamp Server Identity Popover 2021-09-03 17:32:50 +00:00
Snazzah
14c191be60 Fix translation string in Create Bot popover 2021-09-03 10:37:49 -05:00
Paul Makles
240a60919a Merge pull request #167 from KeepSOBP/patch-1 2021-09-03 13:12:26 +01:00
Paul Makles
831f691cda Merge pull request #171 from Rexogamer/preview-padding 2021-09-03 13:05:20 +01:00
Paul
2ccc0b7b5e Change invite rendering logic.
Handle link warnings on embeds.
Remove "EDIT!!" 🙏🙏🙏
2021-09-03 13:04:37 +01:00
Paul Makles
571b30243c Merge pull request #169 from TaiAurori/master 2021-09-03 11:29:46 +01:00
Paul
9adad4a4ab Fix issues introduced by #162.
Switch to more consistent naming scheme.
2021-09-03 11:21:51 +01:00
Paul Makles
966daa6c78 Merge pull request #158 from Snazzah/trusted-links 2021-09-03 11:18:16 +01:00
Paul
60cbc7c9da Add i18n to invalid invite screen. 2021-09-03 11:16:37 +01:00
Paul
57ecf4638e Merge branch 'master' of https://github.com/revoltchat/revite 2021-09-03 11:15:07 +01:00
Paul Makles
4fec0f78cb Merge pull request #161 from Bawbby/master
Clean up invalid invite page.
2021-09-03 11:14:22 +01:00
Paul Makles
5abe90583a Merge pull request #177 from yannickfunk/push-notifications
Parse Web Push notifications
2021-09-03 11:08:14 +01:00
Paul
71ffad9adf Format code for MyBots.tsx, fix i18n and make buttons less aggressive. 2021-09-03 11:07:58 +01:00
Paul Makles
8ad1130a00 Merge pull request #159 from Snazzah/bots-look-cool 2021-09-03 11:04:53 +01:00
Paul Makles
57def75734 Merge pull request #162 from LambdAurora/contextual_border_radius_variables
Introduce new border radius variables for stable theming.
2021-09-03 11:01:30 +01:00
Paul Makles
3aa90ab570 Merge branch 'master' into contextual_border_radius_variables 2021-09-03 11:01:19 +01:00
Paul
bde8b58095 Fix pointer style for badges. 2021-09-03 10:46:52 +01:00
Paul
a1cb72046c Fix and prettier incoming changes from PR #119.
Cherry pick PR #130: don't show add friend button on banned / deleted accounts.
Also account for this in context menu.
2021-09-03 10:43:48 +01:00
Ryan Alexander
a08ad7aa0b Rename "ios" & "fxios" to "Safari" and "Firefox" for browser name (#119) 2021-09-03 09:35:02 +00:00
Paul
c302eade17 Update source links from GitLab to GitHub. 2021-09-03 10:30:27 +01:00
Paul
a387d3c6ae Use variables for scrollbar width.
Update language definitions.
2021-09-03 10:17:42 +01:00
Yannick Funk
591df837d5 Parse push notification packet of client 2021-09-02 23:24:22 +02:00
KeepSOBP
d47827b9d0 Refactor all 2021-09-02 11:35:37 +09:00
Ed L
978f21f04d increase padding for profile preview 2021-09-01 17:02:37 +01:00
TaiAurori
2f950aab53 add visible joining indicator 2021-08-31 21:37:42 +00:00
TaiAurori
a10e5100d3 add proper placeholder for invalid invite 2021-08-31 21:22:19 +00:00
TaiAurori
f9bb332605 reindent 2021-08-31 20:45:01 +00:00
TaiAurori
0b0d1186eb invite embeds 2: electric boogaloo 2021-08-31 20:30:02 +00:00
Snazzah
222d328985 add translation 2021-08-31 16:00:35 +00:00
Snazzah
d298f877e5 finish translations 2021-08-31 15:55:18 +00:00
Snazzah
3ad20d6e96 fix typing errors 2021-08-31 15:37:34 +00:00
KeepSOBP
6836380721 Support multiple architectures for docker
* add github container registry 
* refactor!
2021-08-31 21:51:55 +09:00
Snazzah
4bdc29c9d6 remove under construction tip 2021-08-31 04:51:13 +00:00
Snazzah
8ea0615600 update strings and style 2021-08-31 04:50:48 +00:00
Snazzah
e92877158c update create bot form 2021-08-31 04:33:47 +00:00
Snazzah
28dbd49957 Move creating bots to a popover 2021-08-31 04:00:45 +00:00
Snazzah
d2740f2844 error handling & styling 2021-08-31 03:23:07 +00:00
Snazzah
a76d992db1 Add "add bot" button 2021-08-31 02:33:36 +00:00
Snazzah
430714e816 Bot avatar uploading 2021-08-31 01:42:50 +00:00
TaiAurori
2e9a76519e Merge branch 'master' of https://github.com/TaiAurori/revite 2021-08-30 18:24:35 -04:00
TaiAurori
3d1ee73032 invite embeds preview 2021-08-30 18:21:49 -04:00
LambdAurora
1d42f0a60a Introduce new border radius variables for stable theming. 2021-08-30 23:39:02 +02:00
Bawbby
3046e413cd Clean up invalid invite page.
- Make it look like a valid invite page.
- Add arrow to go back to home.
2021-08-30 17:11:04 -04:00
Snazzah
3678a32d95 Add bot editing 2021-08-30 19:10:55 +00:00
Paul
d368820aeb Add CTRL + ENTER to force send message.
Fix: cursor jumping to the end of message area.
Fix: inconsistent message send button on mobile.
2021-08-30 18:01:32 +01:00
Snazzah
86027f7b3d Initial bot page stylings 2021-08-30 16:18:42 +00:00
Paul
3628aeffdd Select the correct repository. 2021-08-30 16:51:06 +01:00
Paul
4e3e57a7c9 Fix issues introduced in new Typescript version. 2021-08-30 16:45:23 +01:00
Paul
dac6f3dbba Clone submodules for Docker builds. 2021-08-30 16:25:45 +01:00
Paul
b364fe50f6 Make Typescript happy, testing CI build.
Adjust language names.
2021-08-30 16:08:22 +01:00
Paul
17c09baf89 Try to automate Docker builds. 2021-08-30 15:45:18 +01:00
Paul
5631ad8072 Add API URL injection back and Docker builds. 2021-08-30 15:24:15 +01:00
Snazzah
d8465b1aae Add trusted link handling in renderer/prompt 2021-08-30 14:08:13 +00:00
Paul
2a2f711eb5 Fix Korean language name. 2021-08-30 15:01:15 +01:00
Snazzah
4c34787ef3 Add trusted links to state 2021-08-30 13:07:35 +00:00
Paul
0ca99ddceb Fix ghost notifications on closed DMs.
Fix link warning not closing on open.
2021-08-30 13:26:19 +01:00
Paul
44fdee1214 Add new languages: et, fil, ga, ja, ko, lb, ms, nb_NO, sk, sl, ta, vi. 2021-08-30 13:13:15 +01:00
Paul
ea2e6ada82 Merge branch 'master' of https://github.com/revoltchat/revite 2021-08-30 12:35:14 +01:00
Paul
3443565265 Fix observer on Profile pane. 2021-08-30 12:35:12 +01:00
Paul Makles
d4ea64af42 Merge pull request #154 from Snazzah/pr/editbox
Bump message editor rows to 10
2021-08-30 12:19:47 +01:00
Paul Makles
43010b3b72 Merge pull request #151 from ryanalexander/count-direct-messages
Treat direct messages as mention, group behavior is the same
2021-08-30 12:19:29 +01:00
Paul Makles
8d7a05f667 Merge pull request #155 from Snazzah/pr/mail-provider
Update Mail Providers
2021-08-30 12:18:41 +01:00
Paul Makles
912071db3e Merge pull request #150 from ryanalexander/external-link-prompt 2021-08-30 12:17:16 +01:00
Snazzah
ed53cebc01 Update Mail Providers 2021-08-30 05:38:59 +00:00
Snazzah
8a3f0a6629 Bump message editor rows to 10 2021-08-30 05:03:22 +00:00
Ryan Alexander
f3786e473b Treat direct messages as mention, group behaviour is the same 2021-08-29 10:29:58 +10:00
Ryan Alexander
fe04951bcf Make continue button use accent colour 2021-08-29 10:00:23 +10:00
Ryan Alexander
3d0e95d25d Add external link warning 2021-08-29 09:56:20 +10:00
Paul Makles
5c5c9c7d22 Merge pull request #132 from flaree/handle-subdomains 2021-08-26 17:48:28 +01:00
Paul Makles
6e1545412b Merge pull request #131 from ryanalexander/new-voice-interface 2021-08-23 13:31:07 +01:00
Ryan Alexander
dfae11c204 Update UserIcon.tsx 2021-08-23 22:28:49 +10:00
Zomatree
5a716fb1d6 color -> colour 2021-08-23 12:45:12 +01:00
Jamie
2d3afdaa83 fix indentation 2021-08-23 04:42:18 -07:00
Jamie
c4b881a525 Update Renderer.tsx 2021-08-23 04:38:21 -07:00
Ryan Alexander
5be8e60b45 Prevent granting permissions you don't have 2021-08-23 12:32:44 +01:00
Ryan Alexander
c02c4a63fa Only display TextChannels as option for SystemMessage channels 2021-08-23 12:11:19 +01:00
Ryan Alexander
a6846192de Add audio tab and ability to change audio input device 2021-08-23 11:57:46 +01:00
Kamil G
6842bdc4a5 remove search from experiments 2021-08-23 11:52:13 +01:00
Jamie
852cc22dc2 Update Renderer.tsx 2021-08-22 04:31:48 -07:00
Jamie
5c01944cfb Handle subdomains on URLs 2021-08-22 03:39:30 -07:00
Ryan Alexander
af691be15c Update Overview.tsx 2021-08-22 12:26:56 +10:00
Ryan Alexander
f27a07a2da Update Settings.tsx 2021-08-22 12:26:29 +10:00
Ryan Alexander
04e42ae1c2 Delete Privacy.tsx 2021-08-22 12:26:01 +10:00
Ryan Alexander
ccda5e8609 Add deafen button 2021-08-22 12:22:44 +10:00
Paul
db43c02e01 Changes for #88
Fix tooltip foreground.
Change light mode foreground colours.
Update ::selection styles.
2021-08-19 14:50:00 +01:00
Paul Makles
762cad1614 Merge pull request #93 from ryanalexander/patch-4 2021-08-19 13:49:27 +01:00
Ryan Alexander
b60d590385 Update Appearance.tsx 2021-08-19 00:05:23 +10:00
Paul
2341408557 Fix unresolved import for system user ID. 2021-08-18 11:31:25 +01:00
Paul
899593faf0 Try to bump revolt.js and preact-context-menu. I hate javascript 2021-08-18 11:17:37 +01:00
Paul
c51292722a Downgrade Vite to npm:@insertish/vite@2.4.0-beta.3-dynamic-import-css-3c1466b again. 2021-08-18 11:10:55 +01:00
Paul
cb63cf0d92 Upgrade packages but also revert preact-context-menu update. 2021-08-18 11:04:52 +01:00
Paul
d648787e8d Update Vite to 2.5.0 2021-08-18 10:51:58 +01:00
Paul
aa8095725a Update revolt.js to 5.0.1-alpha.6-patch.1 2021-08-18 10:43:15 +01:00
Ryan Alexander
98d1f06ce6 Update Appearance.tsx 2021-08-18 10:11:17 +10:00
Martin Löffler
8825452942 Update preact-context-menu to 0.2.1
Closes #13
2021-08-18 02:01:02 +02:00
Paul Makles
fe24b28bee Merge pull request #104 from ryanalexander/patch-5 2021-08-18 00:59:13 +01:00
Ryan Alexander
993b85843b Update ServerHeader.tsx 2021-08-18 09:58:49 +10:00
Paul Makles
468350b36c Merge pull request #98 from fatalerrorcoded/master 2021-08-18 00:58:45 +01:00
Paul Makles
ae22c344a1 Merge pull request #87 from ryanalexander/context-categories 2021-08-18 00:58:06 +01:00
Ryan Alexander
cfc55a4a9d Delete verified.svg 2021-08-18 09:57:50 +10:00
Ryan Alexander
62ad6ca7d9 Delete revolt_r.svg 2021-08-18 09:57:44 +10:00
Ryan Alexander
70c66f40df Add files via upload 2021-08-18 09:57:33 +10:00
Ryan Alexander
f6b206b74d Add files via upload 2021-08-18 09:57:01 +10:00
Paul
b8c345f493 Add max length to message box. 2021-08-18 00:55:36 +01:00
Ryan Alexander
3d31a6c8f9 Update ServerHeader.tsx 2021-08-18 09:06:57 +10:00
Ryan Alexander
a164cd4016 Add files via upload 2021-08-18 09:06:27 +10:00
Ryan Alexander
7806ece660 Verified badge 2021-08-18 08:55:39 +10:00
Ryan Alexander
cefeebb4d2 Added verified server badge for any servers created by insert 2021-08-18 08:54:55 +10:00
Ryan Alexander
dccc0f4eb7 Update Prompt.tsx 2021-08-18 06:28:18 +10:00
Paul
69cd410aff Fix home tab item width on Firefox.
Fix inability to leave server, for #95.
Add warning to invite bot.
2021-08-17 20:47:44 +01:00
Paul
5bfba2d7cf Show friend request count in indicator. Fixes #96 2021-08-17 20:05:21 +01:00
Martin Löffler
5ab1773f01 Moved reply mention disable into internal event handler 2021-08-17 20:52:16 +02:00
Martin Löffler
29ed48fa70 Disable mention behavior on self-replies 2021-08-17 17:29:25 +02:00
Martin Löffler
b01a3c5554 Hide reply mention button from current user 2021-08-17 17:20:53 +02:00
Paul Makles
ca6bdd332e Merge pull request #90 from ryanalexander/patch-3 2021-08-17 15:33:47 +01:00
Paul
e12efe3533 Improve Home design. 2021-08-17 13:52:02 +01:00
Ryan Alexander
457097ade4 Lowered contrast threshold 2021-08-17 19:33:09 +10:00
Ryan Alexander
5ad4485c64 Transparent will now fallback to the contrasting colour of background
https://github.com/revoltchat/revite/issues/88
2021-08-17 19:30:41 +10:00
Ryan Alexander
66e946f0fc Centered mention count + Fixed file formatting for last commit 2021-08-17 17:19:29 +10:00
Ryan Alexander
49d54ee05a Added create category context menu when right clicking in channel list 2021-08-17 06:31:25 +10:00
Paul
745b03452b Fix chat not scrolling to bottom when messages update. 2021-08-16 18:59:40 +01:00
Paul
d13b5e812d Add leet speak to languages menu. 2021-08-16 18:16:49 +01:00
Paul
1f2e58b10e Include @ symbol when reply is a mention. 2021-08-16 18:08:44 +01:00
Paul
b4f16f0d00 Handle role hoisting / ranking.
Closes #76 and closes #75.
2021-08-16 17:02:24 +01:00
Paul
72e9cda844 Attempt to fix attachments not showing up on Samsung Internet. 2021-08-16 15:16:54 +01:00
Paul Makles
dcb038f986 Merge pull request #83 from ryanalexander/patch-1
Update ContextMenus.tsx
2021-08-15 23:03:17 +01:00
Ryan Alexander
30448ce5a0 Update ContextMenus.tsx
Add Create Invite button to server context menu
2021-08-16 08:00:53 +10:00
Paul
8ba5c13cfc Fix Revolt on WebKit browsers. 2021-08-15 22:58:16 +01:00
Paul Makles
8ca83ad95d Merge pull request #80 from ryanalexander/patch-1 2021-08-15 20:26:06 +01:00
Ryan Alexander
44521716c6 Update ServerListSidebar.tsx 2021-08-16 05:24:37 +10:00
Ryan Alexander
8124119e73 Update ServerListSidebar.tsx 2021-08-16 05:17:21 +10:00
Paul Makles
c99c3ffc35 Merge pull request #79 from ryanalexander/master 2021-08-15 19:29:42 +01:00
Ryan Alexander
9ec2fa54af Removed css changes to appearance tab text 2021-08-16 04:14:39 +10:00
Ryan Alexander
07061c4af1 Update Appearance.tsx 2021-08-16 04:14:10 +10:00
Paul Makles
a17487606f Merge pull request #70 from MichailiK/feature/message/image-loading-background 2021-08-15 18:04:24 +01:00
Paul
d72adacb24 Fix search not working on mobile. 2021-08-15 18:01:25 +01:00
Michaili K
88c9775e23 Create separate ImageFile component for image attachments 2021-08-15 18:53:42 +02:00
Paul Makles
24050a8e05 Merge pull request #74 from ryanalexander/patch-1 2021-08-15 16:59:17 +01:00
Ryan Alexander
a6c788f469 Used global language file for text 2021-08-16 01:57:33 +10:00
Ryan Alexander
3e3c490a22 Add Tooltip to settings icon 2021-08-16 01:40:58 +10:00
Paul
5dbee0c42a oops uh this should be 50% 2021-08-15 15:48:45 +01:00
Paul Makles
a2bc3b8188 Merge pull request #72 from ryanalexander/patch-2 2021-08-15 15:40:18 +01:00
Ryan Alexander
792bc99eac Merge branch 'revoltchat:master' into patch-2 2021-08-16 00:26:18 +10:00
Paul
8a104855a1 Add settings button to server list sidebar.
Move more border radiuses to variables.
2021-08-15 15:21:23 +01:00
Ryan Alexander
6938deb568 Update UserProfile.tsx
Clicking badges that can redirect to a relevant page will do so.

Clicking Supporter will direct to donate page
Clicking Translator will direct to weblate
2021-08-16 00:09:16 +10:00
Paul Makles
ff9545ba2f Merge pull request #66 from janderedev/pr-6 2021-08-15 14:52:12 +01:00
Paul Makles
c0c0c267f4 Merge pull request #67 from ashishcas/fixing-border-radius 2021-08-15 14:50:43 +01:00
Paul
c2485f2a78 Add Thai and Bulgarian. 2021-08-15 14:16:36 +01:00
Michaili K
1b4d1e73df Add (basic implementation of) background for loading images 2021-08-15 12:59:00 +02:00
Paul
4abf98adcb Bump revolt.js to fix objects not being properly updated.
Also don't re-fetch members on each message.
Add cursor: pointer to attachment images upon request.
Use client message cache for replies.
2021-08-15 09:58:22 +01:00
Paul
f59d0efbcb Remember whether reply was a mention or not.
Fix input modals refreshing page.
2021-08-14 21:37:43 +01:00
ashishcas
aedc158654 feat:: updating border radius 2021-08-14 21:44:02 +05:30
Paul
8609a1f016 Try optimise members list. 2021-08-13 22:31:28 +01:00
janderedev
3e1c8c862a Merge branch 'master' of https://github.com/revoltchat/revite into pr-6 2021-08-13 15:54:14 +02:00
Paul
40d0421fa2 Fix inviting bots to servers. 2021-08-12 22:27:14 +01:00
janderedev
dfed9515d1 fix regex, add * and empty text matchers 2021-08-12 23:17:52 +02:00
janderedev
82d3dd3c7b Scroll to bottom after sed editing message 2021-08-12 22:54:54 +02:00
Paul Makles
4d9c324326 Merge pull request #60 from janderedev/pr-5 2021-08-12 21:39:23 +01:00
janderedev
60947b71ed Merge branch 'master' of https://github.com/revoltchat/revite into pr-6 2021-08-12 22:29:41 +02:00
janderedev
884402e62a sed replacement in message box. 2021-08-12 22:21:37 +02:00
Paul
4ac3165bdc Remove logs. 2021-08-12 19:51:23 +01:00
janderedev
ac04bd2b44 Filter mutual servers properly 2021-08-12 18:29:01 +02:00
Paul
c5a36b09d9 Remove ability to add bot as a friend. 2021-08-12 17:11:34 +01:00
janderedev
3d707a64da Merge branch 'master' of https://github.com/revoltchat/revite into pr-5 2021-08-12 17:52:38 +02:00
Paul
f548d91a7c Bump revolt.js version. 2021-08-12 16:17:37 +01:00
Paul
01cdce492e Add bot invite menu. 2021-08-12 16:07:41 +01:00
Paul
237a0024df Temporary bot menu. 2021-08-12 15:29:19 +01:00
Paul
c27f596d40 Show user flags and the bot owner. 2021-08-12 14:40:13 +01:00
Paul
8137409dae Fix search scroll.
Add bot badge.
2021-08-12 12:16:24 +01:00
janderedev
3cc7caefd1 Update translations 2021-08-12 12:46:29 +02:00
Paul Makles
65d44c72bd Merge pull request #59 from janderedev/pr-4 2021-08-12 11:33:44 +01:00
janderedev
1c3d76d45f Added mutual servers tab on user profile 2021-08-12 12:32:56 +02:00
janderedev
72ccbce765 Show member count on invite screen. Fixes #20 2021-08-12 10:45:22 +02:00
Paul Makles
a944ed5040 Merge pull request #58 from brecert/master
fix image overflow on older browsers
2021-08-11 13:44:38 +01:00
Paul
d912e7209f Small fixes for search. 2021-08-11 13:32:31 +01:00
brecert
6f99af6527 fix image overflow on older browsers 2021-08-10 05:48:26 -04:00
Paul
7a80c0edb5 Add search back. 2021-08-09 17:34:25 +01:00
Paul
f19e334d56 Handlers for UserShort.
View user's profile picture.
Close #25, adds logic to hamburger.
2021-08-09 15:51:22 +01:00
Paul
c8b5753211 Anchor scroll to bottom when switching channels. 2021-08-08 23:01:47 +01:00
Paul
8cb02d6d34 Fix users not going offline. 2021-08-08 22:25:57 +01:00
Paul
d5b0d8d9cf Display all server roles separately. 2021-08-08 21:50:29 +01:00
Paul
a19ff58e12 Switch to React Virtuoso from react-window 2021-08-08 20:28:47 +01:00
Paul
a3e2ed3b94 Revert typing indicator changes. 2021-08-08 18:46:27 +01:00
Paul
add94d59ff Temporarily remove TextReact. 2021-08-08 18:40:25 +01:00
Paul
db8dedd3a7 Merge branch 'master' of https://github.com/revoltchat/revite 2021-08-08 18:26:28 +01:00
Paul
5c45e29f92 Improve category design for members list.
Implement new list for groups.
2021-08-08 18:26:16 +01:00
Paul Makles
56caaa75b9 Merge pull request #49 from infi/master
Improve Readme to new format, closes #45
2021-08-08 17:35:47 +01:00
Paul
f2c59ae451 Style categories. 2021-08-08 17:18:58 +01:00
Paul
8e24d1490c Virtualised sidebar test. 2021-08-08 16:17:16 +01:00
Paul
17f68088d1 Show server identity in message replies and typing indicator.
Revert reply connector temporarily.
2021-08-08 10:16:48 +01:00
Paul
ef1eb74486 Don't show server mark as read on channels. 2021-08-07 23:04:44 +01:00
Paul
4f1ba8942f Add server avatars. Closes #52
Add identity edit menu. Closes #51
2021-08-07 22:42:15 +01:00
Paul
97816e1feb Add max-width to settings sidebar. 2021-08-07 21:24:28 +01:00
Infi
318b4b2608 Improve Readme to new format, closes #45 2021-08-07 22:23:50 +02:00
Paul
7c7f813118 Scroll to last position when re-opening a chat. 2021-08-07 20:53:17 +01:00
Paul
1f903cd56b Manage state per channel. Closes #2 2021-08-07 20:43:08 +01:00
Paul
7d76a657fa Fix new state updates. 2021-08-07 16:55:14 +01:00
Paul
4ec1ff5c59 Re-write voice context. Working towards #21 2021-08-07 16:15:55 +01:00
Paul
0fe154c651 Fix voice and abnormal CPU usage. 2021-08-07 14:13:05 +01:00
Paul
0ea80b5717 Fixes #9 and closes #8. This adds a way to mark servers as read.
Servers are also marked as read when joining them.
You can now also mark DMs as read.
2021-08-07 12:30:19 +01:00
Paul
2f06112921 Add a way to copy message links.
Remove focus from auto complete after click, fixes #12.
2021-08-07 10:52:22 +01:00
Paul
bb6ac68c8e Clean up system message code. Fixes #3 2021-08-07 10:32:18 +01:00
Paul Makles
64cfb1f233 Merge pull request #46 from infi/master
Add system message icons. Closes #10
2021-08-07 09:08:41 +01:00
Infi
34e8d54512 Add system message icons. Closes #10 2021-08-07 00:34:57 +02:00
Paul
25615cc16d Bump lang. 2021-08-06 21:16:25 +01:00
Paul Makles
6320eb3253 Merge pull request #44 from janderedev/pr-3 2021-08-06 21:13:14 +01:00
janderedev
fbdbf5d0bc Fix issues with language detection 2021-08-06 22:12:10 +02:00
Paul
7e1698cc79 Refresh the feedback menu. 2021-08-06 21:07:11 +01:00
janderedev
735e9b7f5e Display the system language first. Fixes #4 2021-08-06 20:48:10 +02:00
Paul
973d8adbed Add GitHub links to feedback page. 2021-08-06 18:57:39 +01:00
Paul Makles
cbc5ce9008 Create main.yml 2021-08-06 16:58:31 +00:00
Paul Makles
ae7101a673 Merge pull request #18 from brecert/image-embed-scaling
Improve image embed scaling.
2021-08-06 17:42:32 +01:00
brecert
144a63a5c8 Improve image embed scaling.
- fixes #15
2021-08-06 12:39:23 -04:00
Paul Makles
0d732ededb Merge pull request #17 from janderedev/pr-2
ESC now removes the last attachment. Fixes #16
2021-08-06 17:11:06 +01:00
janderedev
cae3b68c7f ESC now removes the last attachment. Fixes #16 2021-08-06 18:07:11 +02:00
Paul Makles
8d65e1ee11 Merge pull request #14 from janderedev/pr-1 2021-08-06 14:48:15 +01:00
janderedev
1e25821816 Esc now removes the last reply, fixes #7 2021-08-06 15:40:32 +02:00
janderedev
225e14232c Update revolt.js, fixes #1 2021-08-06 14:12:59 +01:00
janderedev
fee3c97e1f Update revolt.js, fixes #1 2021-08-06 14:59:34 +02:00
nizune
1ac5de173b final commit 2021-08-06 09:31:25 +02:00
Paul
d841b9e3cd Fix profiles not loading. 2021-08-05 23:25:49 +01:00
insert
2847318294 Update .gitlab-ci.yml file 2021-08-05 20:19:15 +01:00
Paul
1e7600e867 Fix settings. 2021-08-05 20:19:02 +01:00
Paul
7b45205e01 Format code. 2021-08-05 14:47:20 +01:00
Paul
55e00bf93f Make the linter happy. 2021-08-05 14:47:00 +01:00
nizune
5930415c05 Fixed RTL issue with replies 2021-08-05 12:01:31 +02:00
nizune
123dc6bbfc New look to replies 2021-08-05 11:54:32 +02:00
Paul
f2cf3559db Add Toki Pona SVG. 2021-08-04 19:22:13 +01:00
nizune
fcbd0019a0 Settings account page done 2021-08-04 20:00:30 +02:00
nizune
7a8b12e15c Fixed sent attachments code 2021-08-04 19:59:29 +02:00
nizune
95a149407b Continue work on category buttons 2021-08-04 18:33:01 +02:00
Paul
0aa18d22e9 Remove buttons on Account page. 2021-08-04 16:43:08 +01:00
Paul
b648a7b9ac Large desc option. 2021-08-04 16:17:56 +01:00
Paul
fe75f5a6ca Add i18n to replies.
Add Fluent design category button.
Update Account page with new design.
2021-08-04 16:03:38 +01:00
Paul
8cc92e0c42 Start work on fluent categories.
Fix Locale loading when syncing invalid lang.
2021-08-04 14:31:55 +01:00
nizune
c93f0245f1 Fixed message replies + refined account settings 2021-08-04 14:48:33 +02:00
nizune
1504f307fc Changed Reply bar structure 2021-08-04 14:01:24 +02:00
Paul
184663a3ac Categorise constructed languages. 2021-08-04 12:31:51 +01:00
nizune
6d8a8e14dd Added constructed languages category 2021-08-04 13:29:12 +02:00
nizune
5c9b3a1c86 Finished account settings 2021-08-04 12:56:59 +02:00
Paul
90c46155e4 Add hide email button.
Add device name for Revolt Desktop.
Add Italian and Toki Pona.
2021-08-04 11:40:58 +01:00
nizune
0884df407e Changed button look to plain in account settings 2021-08-04 12:22:48 +02:00
nizune
73c4bf34d6 Changed design of account settings 2021-08-04 12:21:29 +02:00
nizune
907e11bd5e Small fixes to account settings 2021-08-04 11:51:53 +02:00
nizune
3887029f66 Fixed scrollbar out of place in settings menu 2021-08-04 10:49:45 +02:00
nizune
c72df91e3d Cleaned up desktop settings 2021-08-04 10:01:17 +02:00
nizune
f5e2779983 Added detection for multiple attachments.
Co-authored-by: infi <insrt-git@geist.ga>
2021-08-03 22:42:06 +02:00
Paul
4c4477e79e Add new native options. 2021-08-03 20:04:46 +01:00
nizune
f4b04635de Fixed titlebar 2021-08-03 19:30:35 +02:00
nizune
85879faf7b Fixed titlebar 2021-08-03 19:28:22 +02:00
nizune
f25dae77aa Updated boxicons + small fixes 2021-08-03 17:51:35 +02:00
nizune
a10646888f Finished cleaning up User Settings CSS 2021-08-03 17:07:02 +02:00
Paul
e1ffefe2ba Hover animation for home button.
Fix svg alignment in foreign objects.
2021-08-03 15:37:19 +01:00
nizune
9581a4df92 Refreshed languages menu in settings 2021-08-03 11:51:40 +02:00
Paul
0139a91882 Add donation button to home page. 2021-08-02 22:03:59 +01:00
Paul
38dd135f67 Open settings when clicking top left on desktop. 2021-08-02 21:36:49 +01:00
nizune
df39b1fc2b Cleaned up CSS for settings page 2021-08-02 17:55:49 +02:00
nizune
03f572f365 More settings fixes + clamped long usernames 2021-08-02 17:25:39 +02:00
nizune
2f563ef726 More work on settings panel 2021-08-02 16:21:16 +02:00
Paul
f465a8d81f Trick Facebook container extension to disable tracking warning, see issue https://github.com/mozilla/contain-facebook/issues/783 2021-08-02 13:14:10 +01:00
Paul
61680fe386 Merge branch 'master' of https://gitlab.insrt.uk/revolt/revite 2021-08-02 13:13:12 +01:00
nizune
4a248ffa5b Started work on redoing settings structure 2021-08-02 14:09:54 +02:00
Paul
44b5725793 Disallow text selection in messages on mobile. 2021-08-02 13:06:18 +01:00
nizune
ab54afc1e0 Small update for desktop app 2021-08-02 12:22:39 +02:00
nizune
12047ba944 New server sidebar swoosh 2021-08-02 10:57:17 +02:00
nizune
f71b8e82eb Merge branch 'master' of https://gitlab.insrt.uk/revolt/revite 2021-08-02 10:30:05 +02:00
Paul
ed826cf1bb Add settings closing animation. 2021-08-01 21:55:13 +01:00
Paul
fd010ed75e Closing animation for settings. 2021-08-01 21:08:42 +01:00
nizune
f1966b4560 Cleaned up titlebar look 2021-08-01 20:40:02 +01:00
nizune
11c766511a Changed titlebar icons 2021-08-01 20:40:02 +01:00
Paul
d6e32fe8dc Move titlebar. 2021-08-01 20:40:02 +01:00
Paul
591d21c28b Don't show tooltip / hover when no update. 2021-08-01 20:40:02 +01:00
Paul
33baf90d34 Fix iOS touch. 2021-08-01 20:29:36 +01:00
nizune
05f2994a19 Cleaned up titlebar look 2021-08-01 20:41:53 +02:00
nizune
0add738df3 Changed titlebar icons 2021-08-01 19:29:27 +02:00
Paul
0c0dac598e Move titlebar. 2021-08-01 18:11:18 +01:00
Paul
60d09ce747 Don't show tooltip / hover when no update. 2021-08-01 17:56:38 +01:00
Paul
796dc467b8 Move update indicator to titlebar on desktop. 2021-08-01 17:52:44 +01:00
nizune
6baaccd70d Added update button to titlebar 2021-08-01 18:35:10 +02:00
nizune
f1626b9c99 Added fixes to electron titlebar 2021-08-01 18:17:22 +02:00
Paul
4ae0dc6935 Improve titlebar design. 2021-08-01 16:44:51 +01:00
Paul
31636d569c Improved native options. 2021-08-01 14:22:08 +01:00
Paul
63d2d1b760 Fix message links from search. 2021-07-31 22:39:15 +01:00
Paul
8872ed56b1 Fix blocked users appearing in typing indicator.
Make typing indicator time out.
2021-07-31 17:58:26 +01:00
Paul
76478f67be Fix notifications not opening server. 2021-07-31 17:00:50 +01:00
Paul
9bb9d1fa1e Add nicknames + role colours back. 2021-07-31 16:59:37 +01:00
Paul
cc444adef8 Hot fix: Fetch channels for newly found servers. 2021-07-31 16:15:01 +01:00
Paul
909985b47d Fix message links redirecting to home page. 2021-07-31 15:11:58 +01:00
Paul
b95aa3391a Patch revolt.js 2021-07-31 13:56:16 +01:00
Paul
5eed9ecc5e Fix message links from replies. 2021-07-31 13:50:29 +01:00
Paul
6b6279ffee Move typing indicator into revolt.js 2021-07-31 13:48:26 +01:00
Paul
29cc221a34 Fix elements not observing permissions. 2021-07-31 12:09:18 +01:00
Paul
463aa79356 Remove strict on KaTeX, change error. 2021-07-31 11:04:31 +01:00
Paul
719e5b4dd8 Add queued messages back.
Fix various code issues.
i18n invite menu.
2021-07-31 10:31:16 +01:00
Paul
305243ab43 Fix server id not being replaced properly.
Fix links in spoilers opening when revealing.
Fix unread icon appearing for home.
Fix unreads not being acknowledged.
2021-07-31 10:05:59 +01:00
Paul
58d9744fad Update to revolt.js 5.0.0-alpha.10
Fix member sidebar not showing on mobile.
2021-07-31 09:34:55 +01:00
Paul
bdd93e8840 Fix duplicate member entries. 2021-07-30 23:43:26 +01:00
Paul
4c9554c5e9 Zero error milestone. 2021-07-30 22:40:49 +01:00
Paul
c21453b281 100 error milestone.
Remove hooks completely. :)
2021-07-30 21:20:42 +01:00
Paul
3184269ba4 Start migration to revolt.js@5.0.0.
200 error milestone
2021-07-30 20:24:53 +01:00
Paul
564c1d8494 Completely remove all references to Username. 2021-07-29 21:47:45 +01:00
Paul
0397700b88 Try reverting change to typing indicator. 2021-07-29 21:43:04 +01:00
Paul
6531486636 Handle additional side effects from events. 2021-07-29 21:23:06 +01:00
Paul
b0681dfc99 Load member sidebar into MobX state. 2021-07-29 21:01:03 +01:00
Paul
b06729d0b3 Handle all packets. 2021-07-29 20:39:58 +01:00
Paul
d5cd45196e Clean up code. 2021-07-29 20:11:50 +01:00
Paul
768c80b051 Remove useServer and useServers. 2021-07-29 19:01:40 +01:00
Paul
bde9a2e8f7 Remove useChannels.
Add servers to MobX.
2021-07-29 18:49:49 +01:00
Paul
411fac2527 Remove useChannel 2021-07-29 18:41:01 +01:00
Paul
0571c065bd Remove remaining references to useUser(s).
Add Channel object.
2021-07-29 16:55:07 +01:00
Paul
748713be53 Fix: Should use observer not observable. 2021-07-29 16:08:35 +01:00
Paul
f8611ddea5 Finish migrating user state over to MobX. 2021-07-29 15:51:19 +01:00
Paul
4dffaad6c1 Work towards removing useUsers. 2021-07-29 15:11:21 +01:00
Paul
cf3930b094 Add MobX store, create observable User. 2021-07-29 12:41:28 +01:00
Paul
781fa5de10 Attempt to fix no permission on server. 2021-07-28 17:55:53 +01:00
Paul
25fa375ce0 Fix typing indicator. 2021-07-28 14:04:27 +01:00
Paul
98f9672801 Show nickname / role colour in typing indicator.
Try to fix voice context.
2021-07-27 11:45:45 +01:00
Paul
a8c3482815 Temporary member nickname / role colour solution. 2021-07-25 17:52:57 +01:00
Paul
e61c647fda Update donation link.
Add settings tip to home page.
2021-07-25 14:37:19 +01:00
Paul
6d5fb0a8a3 Rename occurrences of monoscape to monospace. 2021-07-25 14:26:45 +01:00
Paul
6cf18b1b9b Fix message reply overflow.
Add opera icon to sessions.
2021-07-25 14:18:48 +01:00
Paul
f2a69daf03 Fix onboarding. 2021-07-25 13:55:45 +01:00
Paul
fd03c64d92 Show friend requests on top-right avatar. 2021-07-25 12:50:34 +01:00
Paul
e12ebc9b0d Fix scrollbar on server list. 2021-07-25 10:56:22 +01:00
Paul
8c6947f7d4 Add category editor to servers. 2021-07-24 19:39:41 +01:00
Paul
71020e6e8c Bring back ability to edit roles on members.
Improve ban list design.
2021-07-24 18:46:33 +01:00
Paul
dbaf246c27 Use loading="lazy" in more places.
i18n invites page.
Polish the bans page.
2021-07-24 17:01:50 +01:00
Paul
ca975aae7b Lazy load embed contents.
Use server config for image proxy.
2021-07-24 11:22:08 +01:00
nizune
95a7ee405d Fixed app to portrait only mode for the time being 2021-07-23 18:55:18 +00:00
Paul
38157ae14b Add search sorting. 2021-07-21 18:27:05 +01:00
Paul
f5e70afb35 Experimental hooks. 2021-07-14 14:42:22 +01:00
Paul
7374591458 Add editing role name / colour.
Animate avatars on message hover.
Switch to 24-hour time format by default.
2021-07-14 13:25:40 +01:00
290 changed files with 13711 additions and 6699 deletions

7
.dockerignore Normal file
View File

@@ -0,0 +1,7 @@
.github
.vscode
dist
dist_injected
node_modules
.env
.env.local

2
.env
View File

@@ -1,2 +1,2 @@
VITE_API_URL=https://api.revolt.chat
VITE_THEMES_URL=https://static.revolt.chat/themes
VITE_THEMES_URL=https://themes.revolt.chat

2
.env.build Normal file
View File

@@ -0,0 +1,2 @@
VITE_API_URL=__API_URL__
VITE_THEMES_URL=https://themes.revolt.chat

1
.github/FUNDING.yml vendored
View File

@@ -1 +1,2 @@
ko_fi: insertish
custom: https://insrt.uk/donate

24
.github/SECURITY.md vendored Normal file
View File

@@ -0,0 +1,24 @@
# Security
## Reporting a Vulnerability
If you would like to report a security vulnerability,
please email **[security@revolt.chat](mailto:security@revolt.chat)**,
this will open a new ticket in ticket system, you should receive a response
within the next couple of days, potentially within a few minutes if someone
is currently active.
To help us best triage the issue, please provide:
- The type of issue at hand
- The name of the relevant project affected
- Reproduction steps
- Reference to any relevant source file(s) that you may suspect are causing the issue
- Any extra information about your configuration.
- Description of potential ways this can be exploited, if you can list any
For revoltchat/revite in particular:
- Please include the commit hash of the client, it is visible in settings under the log out button.
Thank you for helping Revolt.

33
.github/actions/build/action.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Build
description: Builds a project instance, assuming all the correct project files are in the build folder
inputs:
base:
name: Base path
description: The path to use as a base for linking
required: true
default: /
folder:
name: Build Folder
description: The folder to try to build from
required: true
default: .
runs:
using: composite
steps:
- name: Setup Node
uses: actions/setup-node@v2
with:
node-version: 15
cache: "yarn"
- name: Install Dependencies and Build
shell: bash -l {0}
env:
BUILD_FOLDER: ${{ inputs.folder }}
BASE: ${{ inputs.base }}
run: |
cd "$BUILD_FOLDER"
yarn install
yarn build --base "$BASE"

111
.github/workflows/docker.yml vendored Normal file
View File

@@ -0,0 +1,111 @@
name: Docker
on:
push:
branches:
- "master"
tags:
- "v*"
paths-ignore:
- ".github/**"
- "!.github/workflows/docker.yml"
- "!.github/workflows/preview_*.yml"
- ".vscode/**"
- ".gitignore"
- ".gitlab-ci.yml"
- "LICENSE"
- "README"
pull_request:
branches:
- "master"
paths-ignore:
- ".github/**"
- "!.github/workflows/docker.yml"
- "!.github/workflows/preview_*.yml"
- ".vscode/**"
- ".gitignore"
- ".gitlab-ci.yml"
- "LICENSE"
- "README"
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
architecture: [linux/amd64]
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: "recursive"
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache/${{ matrix.architecture }}
key: ${{ runner.os }}-buildx-${{ matrix.architecture }}-${{ github.sha }}
- name: Build
uses: docker/build-push-action@v2
with:
context: .
platforms: ${{ matrix.architecture }}
cache-from: type=local,src=/tmp/.buildx-cache/${{ matrix.architecture }}
cache-to: type=local,dest=/tmp/.buildx-cache-new/${{ matrix.architecture }},mode=max
- name: Move cache
run: |
rm -rf /tmp/.buildx-cache/${{ matrix.architecture }}
mv /tmp/.buildx-cache-new/${{ matrix.architecture }} /tmp/.buildx-cache/${{ matrix.architecture }}
publish:
needs: [test]
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: "recursive"
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Cache amd64 Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache/linux/amd64
key: ${{ runner.os }}-buildx-linux/amd64-${{ github.sha }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v3
with:
images: revoltchat/client, ghcr.io/revoltchat/client
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to Github Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and publish
uses: docker/build-push-action@v2
with:
context: .
push: true
platforms: linux/amd64,linux/arm64,linux/arm/v7
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=local,src=/tmp/.buildx-cache/linux/amd64
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
- name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache

13
.github/workflows/mirroring.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
name: Mirroring
on: [push, delete]
jobs:
to_gitlab:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v1
- uses: pixta-dev/repository-mirroring-action@v1
with:
target_repo_url: git@gitlab.com:insert/revolt-vite.git
ssh_private_key: ${{ secrets.GITLAB_SSH_PRIVATE_KEY }}

39
.github/workflows/preview_cleanup.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: Clean Preview
#! Safety:
#! this workflow should not execute any untrusted input at all
#! see the docs on `pull_request_target` for more
on:
pull_request_target:
types: [unlabeled]
jobs:
clean:
runs-on: ubuntu-latest
if: github.event.label.name == 'use-preview'
env:
BASE: refs/pull/${{ github.event.pull_request.number }}
steps:
- uses: actions/checkout@v2
with:
ref: build-previews
persist-credentials: false
- name: clean previews
run: rm -rf "$BASE"
- name: publish cleaned previews
uses: JamesIves/github-pages-deploy-action@4.1.5
with:
folder: .
branch: build-previews
commit-message: "Cleaning up build result for #${{ github.event.pull_request.number }}"
- name: send comment
uses: marocchino/sticky-pull-request-comment@v2
with:
header: Preview environment
message: |
## Preview environment
There is no longer a preview enviroment for this pull request due to the `use-preview` label being removed

View File

@@ -0,0 +1,52 @@
name: Preview Pull Request
#! Safety:
#! this workflow should not execute any untrusted input at all
#! see the docs on `pull_request_target` for more
on:
pull_request_target:
types: [synchronize, reopened, labeled]
jobs:
preview:
runs-on: ubuntu-latest
# make sure the pull request is labeled with 'use-preview'
if: github.event.label.name == 'use-preview' || contains(github.event.pull_request.labels.*.name, 'use-preview')
env:
BASE: refs/pull/${{ github.event.pull_request.number }}/merge
REPO: ${{ github.event.repository.name }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v2
with:
# Head commit of the pull request
ref: ${{ github.event.pull_request.head.sha }}
path: pull
submodules: recursive
- name: build
uses: ./.github/actions/build
with:
base: /${{ env.REPO }}/${{ env.BASE }}/
folder: pull
- name: publish preview
uses: JamesIves/github-pages-deploy-action@4.1.5
with:
folder: pull/dist
branch: build-previews
target-folder: ${{ env.BASE }}
single-commit: true
commit-message: "Publishing build result from #${{ github.event.pull_request.number }}"
- name: send comment
uses: marocchino/sticky-pull-request-comment@v2
with:
header: Preview environment
message: |
## Preview environment
https://${{ github.repository_owner }}.github.io/${{ env.REPO }}/${{ env.BASE }}/
This link will remain active until the `use-preview` label is removed.

49
.github/workflows/triage_issue.yml vendored Normal file
View File

@@ -0,0 +1,49 @@
name: Add Issue to Board
on:
issues:
types: [opened]
jobs:
track_issue:
runs-on: ubuntu-latest
steps:
- name: Get project data
env:
GITHUB_TOKEN: ${{ secrets.PAT }}
run: |
gh api graphql -f query='
query {
organization(login: "revoltchat"){
projectNext(number: 3) {
id
fields(first:20) {
nodes {
id
name
settings
}
}
}
}
}' > project_data.json
echo 'PROJECT_ID='$(jq '.data.organization.projectNext.id' project_data.json) >> $GITHUB_ENV
echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV
echo 'TODO_OPTION_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") |.settings | fromjson.options[] | select(.name=="Todo") |.id' project_data.json) >> $GITHUB_ENV
- name: Add issue to project
env:
GITHUB_TOKEN: ${{ secrets.PAT }}
ISSUE_ID: ${{ github.event.issue.node_id }}
run: |
item_id="$( gh api graphql -f query='
mutation($project:ID!, $issue:ID!) {
addProjectNextItem(input: {projectId: $project, contentId: $issue}) {
projectNextItem {
id
}
}
}' -f project=$PROJECT_ID -f issue=$ISSUE_ID --jq '.data.addProjectNextItem.projectNextItem.id')"
echo 'ITEM_ID='$item_id >> $GITHUB_ENV

72
.github/workflows/triage_pr.yml vendored Normal file
View File

@@ -0,0 +1,72 @@
name: Add PR to Board
on:
pull_request_target:
types: [opened]
jobs:
track_pr:
runs-on: ubuntu-latest
steps:
- name: Get project data
env:
GITHUB_TOKEN: ${{ secrets.PAT }}
run: |
gh api graphql -f query='
query {
organization(login: "revoltchat"){
projectNext(number: 3) {
id
fields(first:20) {
nodes {
id
name
settings
}
}
}
}
}' > project_data.json
echo 'PROJECT_ID='$(jq '.data.organization.projectNext.id' project_data.json) >> $GITHUB_ENV
echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV
echo 'INCOMING_OPTION_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") |.settings | fromjson.options[] | select(.name=="Incoming PRs") |.id' project_data.json) >> $GITHUB_ENV
- name: Add PR to project
env:
GITHUB_TOKEN: ${{ secrets.PAT }}
PR_ID: ${{ github.event.pull_request.node_id }}
run: |
item_id="$( gh api graphql -f query='
mutation($project:ID!, $pr:ID!) {
addProjectNextItem(input: {projectId: $project, contentId: $pr}) {
projectNextItem {
id
}
}
}' -f project=$PROJECT_ID -f pr=$PR_ID --jq '.data.addProjectNextItem.projectNextItem.id')"
echo 'ITEM_ID='$item_id >> $GITHUB_ENV
- name: Set fields
env:
GITHUB_TOKEN: ${{ secrets.PAT }}
run: |
gh api graphql -f query='
mutation (
$project: ID!
$item: ID!
$status_field: ID!
$status_value: String!
) {
set_status: updateProjectNextItemField(input: {
projectId: $project
itemId: $item
fieldId: $status_field
value: $status_value
}) {
projectNextItem {
id
}
}
}' -f project=$PROJECT_ID -f item=$ITEM_ID -f status_field=$STATUS_FIELD_ID -f status_value=${{ env.INCOMING_OPTION_ID }} --silent

7
.gitignore vendored
View File

@@ -1,5 +1,12 @@
node_modules
.DS_Store
dist
dist_injected
dist-ssr
*.local
*.log
/.idea
public/assets
public/assets_*
!public/assets_default

40
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,40 @@
image: node:14-buster
variables:
GIT_SUBMODULE_STRATEGY: recursive
cache:
paths:
- node_modules
# Fetch dependencies and setup project for compilation.
install:
stage: prepare
script:
- yarn
# Type check the project
typecheck:
stage: test
needs:
- install
dependencies:
- install
script:
- yarn typecheck
# Lint the project and check prettier output.
lint:
stage: test
allow_failure: true
needs:
- install
dependencies:
- install
script:
- yarn lint
- yarn --check 'src/**/*.{js,jsx,ts,tsx}'
stages:
- prepare
- test

2
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "external/lang"]
path = external/lang
url = https://gitlab.insrt.uk/revolt/translations
url = https://github.com/revoltchat/translations

View File

@@ -1,8 +1,14 @@
module.exports = {
"tabWidth": 4,
"trailingComma": "all",
"jsxBracketSameLine": true,
"importOrder": ["preact|classnames|.scss$", "/(lib)", "/(redux)", "/(context)", "/(ui|common)|.svg$", "^[./]"],
"importOrderSeparation": true,
}
tabWidth: 4,
trailingComma: "all",
jsxBracketSameLine: true,
importOrder: [
"preact|classnames|.scss$",
"/(lib)",
"/(redux|mobx)",
"/(context)",
"/(ui|common)|.svg|.webp|.png|.jpg$",
"^[./]",
],
importOrderSeparation: true,
};

View File

@@ -1,3 +1,7 @@
{
"recommendations": ["esbenp.prettier-vscode"]
"recommendations": [
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"kol.commit-lint"
]
}

View File

@@ -1,4 +1,5 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
"editor.formatOnSave": true,
"compile-hero.disable-compile-files-on-did-save-code": true
}

20
Dockerfile Normal file
View File

@@ -0,0 +1,20 @@
FROM node:16-buster AS builder
WORKDIR /usr/src/app
COPY package*.json ./
RUN yarn --no-cache
COPY . .
COPY .env.build .env
RUN yarn add --dev @babel/plugin-proposal-decorators
RUN yarn typecheck
RUN yarn build
RUN npm prune --production
FROM node:16-buster
WORKDIR /usr/src/app
COPY --from=builder /usr/src/app .
EXPOSE 5000
CMD [ "yarn", "start:inject" ]

View File

@@ -1,21 +1,57 @@
# Revite
## Description
This is the web client for Revolt, which is also available live at [app.revolt.chat](https://app.revolt.chat).
You can track progress on the client on [our Wekan board](https://wekan.insrt.uk/b/jj3x5C6nbYzM6ERQD/revolt).
## Stack
Official screenshots of the client are available in [this Google Drive folder](https://drive.google.com/drive/folders/1Ckhl7_9OTTaKzyisrWHzZw1hHj55JwhD).
- [Preact](https://preactjs.com/)
- [Vite](https://vitejs.dev/)
## Submodule Hint
This project contains submodules. Run `git submodule init` after you clone this repository to initialize the submodules.
It is also recommended to run `git submodule update` after you pull from upstream.
## Resources
### Revite
- [Revite Issue Board](https://github.com/revoltchat/revite/issues)
- [Google Drive Folder with Screenshots](https://drive.google.com/drive/folders/1Ckhl7_9OTTaKzyisrWHzZw1hHj55JwhD)
### Revolt
- [Revolt Project Board](https://github.com/revoltchat/revolt/discussions) (Submit feature requests here)
- [Revolt Testers Server](https://app.revolt.chat/invite/Testers)
- [Contribution Guide](https://developers.revolt.chat/contributing)
## Quick Start
Get revite up and running locally.
```
git clone --recursive https://github.com/revoltchat/revite
cd revite
yarn
yarn dev
```
## CLI Commands
* `yarn dev`: Runs a development server.
| Command | Description |
| ------------------- | -------------------------------------------- |
| `yarn pull` | Setup assets required for Revite. |
| `yarn dev` | Start the Revolt client in development mode. |
| `yarn build` | Build the Revolt client. |
| `yarn preview` | Start a local server with the built client. |
| `yarn lint` | Run ESLint on the client. |
| `yarn fmt` | Run Prettier on the client. |
| `yarn typecheck` | Run TypeScript type checking on the client. |
| `yarn start` | Start a local sirv server with built client. |
| `yarn start:inject` | Inject a given API URL and start server. |
* `yarn build`: Creates a production build of the client.
## License
* `yarn preview`: Starts a local server with the production build.
* `yarn lint`: Runs ESLint to check project.
* `yarn fmt`: Runs prettier on source code.
* `yarn typecheck`: Runs Typescript compiler in noEmit mode.
Revite is licensed under the [GNU Affero General Public License v3.0](https://github.com/revoltchat/revite/blob/master/LICENSE).

View File

@@ -1 +1 @@
1.0.0-vite
0.5.3-1

2
external/lang vendored

View File

@@ -1,37 +1,82 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Revolt</title>
<meta name="apple-mobile-web-app-title" content="Revolt">
<head>
<meta charset="UTF-8" />
<title>Revolt</title>
<meta name="apple-mobile-web-app-title" content="Revolt" />
<!--<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no"
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<!--App Icons-->
<link rel="apple-touch-icon" href="public/assets/icons/apple-touch.png">
<link rel="icon" type="image/png" href="/src/assets/logo_round.png" />
<!--App Icons-->
<link
rel="apple-touch-icon"
href="public/assets/icons/apple-touch.png"
/>
<link rel="icon" type="image/png" href="/assets/logo_round.png" />
<!--Splash Screens for iOS Devices-->
<link href="public/assets/splashscreens/iphone5_splash.png" media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
<link href="public/assets/splashscreens/iphone6_splash.png" media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
<link href="public/assets/splashscreens/iphoneplus_splash.png" media="(device-width: 621px) and (device-height: 1104px) and (-webkit-device-pixel-ratio: 3)" rel="apple-touch-startup-image" />
<link href="public/assets/splashscreens/iphonex_splash.png" media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3)" rel="apple-touch-startup-image" />
<link href="public/assets/splashscreens/iphonexr_splash.png" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
<link href="public/assets/splashscreens/iphonexsmax_splash.png" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3)" rel="apple-touch-startup-image" />
<link href="public/assets/splashscreens/ipad_splash.png" media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
<link href="public/assets/splashscreens/ipadpro1_splash.png" media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
<link href="public/assets/splashscreens/ipadpro3_splash.png" media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
<link href="public/assets/splashscreens/ipadpro2_splash.png" media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image" />
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
<style>
html {
background-color: #191919;
}
</style>
<!--Splash Screens for iOS Devices-->
<link
href="public/assets/splashscreens/iphone5_splash.png"
media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)"
rel="apple-touch-startup-image"
/>
<link
href="public/assets/splashscreens/iphone6_splash.png"
media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)"
rel="apple-touch-startup-image"
/>
<link
href="public/assets/splashscreens/iphoneplus_splash.png"
media="(device-width: 621px) and (device-height: 1104px) and (-webkit-device-pixel-ratio: 3)"
rel="apple-touch-startup-image"
/>
<link
href="public/assets/splashscreens/iphonex_splash.png"
media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3)"
rel="apple-touch-startup-image"
/>
<link
href="public/assets/splashscreens/iphonexr_splash.png"
media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2)"
rel="apple-touch-startup-image"
/>
<link
href="public/assets/splashscreens/iphonexsmax_splash.png"
media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3)"
rel="apple-touch-startup-image"
/>
<link
href="public/assets/splashscreens/ipad_splash.png"
media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2)"
rel="apple-touch-startup-image"
/>
<link
href="public/assets/splashscreens/ipadpro1_splash.png"
media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2)"
rel="apple-touch-startup-image"
/>
<link
href="public/assets/splashscreens/ipadpro3_splash.png"
media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2)"
rel="apple-touch-startup-image"
/>
<link
href="public/assets/splashscreens/ipadpro2_splash.png"
media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2)"
rel="apple-touch-startup-image"
/>
</head>
<body onContextMenu="return false" ontouchstart="">
<div id="app"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
<style>
html {
background-color: #191919;
}
</style>
</html>

View File

@@ -1,109 +1,144 @@
{
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "rimraf build && vite build",
"preview": "vite preview",
"lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'",
"fmt": "prettier --write 'src/**/*.{js,jsx,ts,tsx}'",
"typecheck": "tsc --noEmit"
},
"eslintConfig": {
"parser": "@typescript-eslint/parser",
"extends": [
"preact",
"plugin:@typescript-eslint/recommended"
],
"ignorePatterns": [
"build/"
],
"rules": {
"@typescript-eslint/explicit-module-boundary-types": "off"
}
},
"dependencies": {
"preact": "^10.5.13"
},
"devDependencies": {
"@fontsource/atkinson-hyperlegible": "^4.4.5",
"@fontsource/bree-serif": "^4.4.5",
"@fontsource/comic-neue": "^4.4.5",
"@fontsource/fira-code": "^4.4.5",
"@fontsource/inter": "^4.4.5",
"@fontsource/lato": "^4.4.5",
"@fontsource/montserrat": "^4.4.5",
"@fontsource/noto-sans": "^4.4.5",
"@fontsource/open-sans": "^4.4.5",
"@fontsource/poppins": "^4.4.5",
"@fontsource/raleway": "^4.4.5",
"@fontsource/roboto": "^4.4.5",
"@fontsource/roboto-mono": "^4.4.5",
"@fontsource/source-code-pro": "^4.4.5",
"@fontsource/space-mono": "^4.4.5",
"@fontsource/ubuntu": "^4.4.5",
"@fontsource/ubuntu-mono": "^4.4.5",
"@hcaptcha/react-hcaptcha": "^0.3.6",
"@preact/preset-vite": "^2.0.0",
"@rollup/plugin-replace": "^2.4.2",
"@styled-icons/boxicons-logos": "^10.34.0",
"@styled-icons/boxicons-regular": "^10.34.0",
"@styled-icons/boxicons-solid": "^10.34.0",
"@styled-icons/simple-icons": "^10.33.0",
"@tippyjs/react": "^4.2.5",
"@traptitech/markdown-it-katex": "^3.4.3",
"@traptitech/markdown-it-spoiler": "^1.1.6",
"@trivago/prettier-plugin-sort-imports": "^2.0.2",
"@types/lodash.defaultsdeep": "^4.6.6",
"@types/lodash.isequal": "^4.5.5",
"@types/markdown-it": "^12.0.2",
"@types/node": "^15.12.4",
"@types/preact-i18n": "^2.3.0",
"@types/prismjs": "^1.16.5",
"@types/react-helmet": "^6.1.1",
"@types/react-router-dom": "^5.1.7",
"@types/react-scroll": "^1.8.2",
"@types/styled-components": "^5.1.10",
"@types/twemoji": "^12.1.1",
"@typescript-eslint/eslint-plugin": "^4.27.0",
"@typescript-eslint/parser": "^4.27.0",
"classnames": "^2.3.1",
"dayjs": "^1.10.6",
"detect-browser": "^5.2.0",
"eslint": "^7.28.0",
"eslint-config-preact": "^1.1.4",
"eventemitter3": "^4.0.7",
"highlight.js": "^11.0.1",
"idb": "^6.1.2",
"localforage": "^1.9.0",
"lodash.defaultsdeep": "^4.6.1",
"lodash.isequal": "^4.5.0",
"markdown-it": "^12.0.6",
"markdown-it-emoji": "^2.0.0",
"markdown-it-sub": "^1.0.0",
"markdown-it-sup": "^1.0.0",
"mediasoup-client": "npm:@insertish/mediasoup-client@3.6.36-esnext",
"preact-context-menu": "^0.1.5",
"preact-i18n": "^2.4.0-preactx",
"prettier": "^2.3.1",
"prismjs": "^1.23.0",
"react-device-detect": "^1.17.0",
"react-helmet": "^6.1.0",
"react-hook-form": "6.3.0",
"react-overlapping-panels": "1.2.2",
"react-redux": "^7.2.4",
"react-router-dom": "^5.2.0",
"react-scroll": "^1.8.2",
"redux": "^4.1.0",
"revolt.js": "4.3.3-alpha.14",
"rimraf": "^3.0.2",
"sass": "^1.35.1",
"shade-blend-color": "^1.0.0",
"styled-components": "^5.3.0",
"typescript": "^4.3.2",
"ulid": "^2.3.0",
"use-resize-observer": "^7.0.0",
"vite": "npm:@insertish/vite@2.4.0-beta.3-dynamic-import-css-3c1466b",
"vite-plugin-pwa": "^0.8.1",
"workbox-precaching": "^6.1.5"
}
"version": "0.0.0",
"scripts": {
"dev": "node scripts/setup_assets.js --check && vite",
"pull": "node scripts/setup_assets.js",
"build": "rimraf build && node scripts/setup_assets.js --check && vite build",
"preview": "vite preview",
"lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'",
"fmt": "prettier --write 'src/**/*.{js,jsx,ts,tsx}'",
"typecheck": "tsc --noEmit",
"start": "sirv dist --cors --single --host",
"start:inject": "node scripts/inject.js && sirv dist_injected --cors --single --host"
},
"eslintConfig": {
"parser": "@typescript-eslint/parser",
"extends": [
"preact",
"plugin:@typescript-eslint/recommended"
],
"ignorePatterns": [
"build/"
],
"rules": {
"radix": "off",
"no-spaced-func": "off",
"react/no-danger": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-unused-vars": [
"warn",
{
"varsIgnorePattern": "^_"
}
],
"no-unused-vars": [
"warn",
{
"varsIgnorePattern": "^_"
}
]
}
},
"dependencies": {
"fs-extra": "^10.0.0",
"klaw": "^3.0.0",
"react-beautiful-dnd": "^13.1.0",
"sirv-cli": "^1.0.14",
"vite": "^2.6.14"
},
"devDependencies": {
"@fontsource/atkinson-hyperlegible": "^4.4.5",
"@fontsource/bree-serif": "^4.4.5",
"@fontsource/comic-neue": "^4.4.5",
"@fontsource/fira-code": "^4.4.5",
"@fontsource/inter": "^4.4.5",
"@fontsource/jetbrains-mono": "^4.4.5",
"@fontsource/lato": "^4.4.5",
"@fontsource/montserrat": "^4.4.5",
"@fontsource/noto-sans": "^4.4.5",
"@fontsource/open-sans": "^4.4.5",
"@fontsource/poppins": "^4.4.5",
"@fontsource/raleway": "^4.4.5",
"@fontsource/roboto": "^4.4.5",
"@fontsource/roboto-mono": "^4.4.5",
"@fontsource/source-code-pro": "^4.4.5",
"@fontsource/space-mono": "^4.4.5",
"@fontsource/ubuntu": "^4.4.5",
"@fontsource/ubuntu-mono": "^4.4.5",
"@hcaptcha/react-hcaptcha": "^0.3.6",
"@preact/preset-vite": "^2.0.0",
"@rollup/plugin-replace": "^2.4.2",
"@styled-icons/boxicons-logos": "^10.34.0",
"@styled-icons/boxicons-regular": "^10.34.0",
"@styled-icons/boxicons-solid": "^10.37.0",
"@styled-icons/simple-icons": "^10.33.0",
"@tippyjs/react": "^4.2.5",
"@traptitech/markdown-it-katex": "^3.4.3",
"@traptitech/markdown-it-spoiler": "^1.1.6",
"@trivago/prettier-plugin-sort-imports": "^2.0.2",
"@types/lodash.defaultsdeep": "^4.6.6",
"@types/lodash.isequal": "^4.5.5",
"@types/markdown-it": "^12.0.2",
"@types/node": "^15.12.4",
"@types/preact-i18n": "^2.3.0",
"@types/prismjs": "^1.16.5",
"@types/react-beautiful-dnd": "^13.1.2",
"@types/react-helmet": "^6.1.1",
"@types/react-router-dom": "^5.1.7",
"@types/react-scroll": "^1.8.2",
"@types/react-virtualized-auto-sizer": "^1.0.1",
"@types/styled-components": "^5.1.10",
"@types/twemoji": "^12.1.1",
"@typescript-eslint/eslint-plugin": "^4.27.0",
"@typescript-eslint/parser": "^4.27.0",
"classnames": "^2.3.1",
"dayjs": "^1.10.6",
"detect-browser": "^5.2.0",
"eslint": "^7.28.0",
"eslint-config-preact": "^1.1.4",
"eventemitter3": "^4.0.7",
"highlight.js": "^11.0.1",
"localforage": "^1.9.0",
"lodash.defaultsdeep": "^4.6.1",
"lodash.isequal": "^4.5.0",
"markdown-it": "^12.0.6",
"markdown-it-emoji": "^2.0.0",
"markdown-it-sub": "^1.0.0",
"markdown-it-sup": "^1.0.0",
"mediasoup-client": "npm:@insertish/mediasoup-client@3.6.36-esnext",
"mobx": "^6.3.2",
"mobx-react-lite": "^3.2.0",
"preact": "^10.5.14",
"preact-context-menu": "^0.2.1",
"preact-i18n": "^2.4.0-preactx",
"prettier": "^2.3.1",
"prismjs": "^1.23.0",
"react-device-detect": "^1.17.0",
"react-helmet": "^6.1.0",
"react-hook-form": "6.3.0",
"react-overlapping-panels": "1.2.2",
"react-redux": "^7.2.4",
"react-router-dom": "^5.2.0",
"react-scroll": "^1.8.2",
"react-virtualized-auto-sizer": "^1.0.5",
"react-virtuoso": "^1.10.4",
"redux": "^4.1.0",
"revolt-api": "0.5.3-alpha.10",
"revolt.js": "^5.1.0-alpha.10",
"rimraf": "^3.0.2",
"sass": "^1.35.1",
"shade-blend-color": "^1.0.0",
"styled-components": "^5.3.0",
"typescript": "^4.4.2",
"ulid": "^2.3.0",
"use-resize-observer": "^7.0.0",
"vite-plugin-pwa": "^0.8.1",
"workbox-precaching": "^6.1.5"
},
"name": "client",
"main": "index.js",
"repository": "https://github.com/revoltchat/revite.git",
"author": "Paul <paulmakles@gmail.com>",
"license": "MIT"
}

View File

@@ -1,4 +0,0 @@
<svg width="343" height="343" viewBox="0 0 343 343" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M163.994 101.423C163.994 118.65 154.621 128.991 134.617 128.991H101.497V74.4793H134.623C154.621 74.4793 163.994 85.1293 163.994 101.423ZM16 30L48.0653 74.5844V249.881H101.503V166.887H114.317L159.948 249.899H220.262L169.636 162.814C183.771 159.366 196.307 151.183 205.17 139.62C214.033 128.057 218.692 113.807 218.375 99.2285C218.375 61.0106 191.502 30 137.749 30H48.0653H16Z" fill="#EFAB44" stroke="#EFAB44" stroke-width="0.97733"/>
<path d="M323.215 148.038L280.59 190.653L241.854 151.906L284.469 109.292C258.674 98.6844 227.937 103.835 206.997 124.797C186.057 145.737 180.895 176.485 191.503 202.28L122.731 271.04C118.447 275.324 118.447 282.25 122.731 286.534L145.984 309.787C150.268 314.071 157.194 314.071 161.478 309.787L230.238 241.015C256.033 251.622 286.781 246.461 307.721 225.521C328.661 204.57 333.812 173.822 323.215 148.038Z" fill="#99AAB5"/>
</svg>

Before

Width:  |  Height:  |  Size: 973 B

View File

@@ -1,4 +0,0 @@
<svg width="343" height="343" viewBox="0 0 343 343" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M252.571 30L333.429 171.5L252.571 313H90.8571L10 171.5L90.8571 30H252.571Z" fill="#509AF0"/>
<path d="M164.486 82.3018C182.31 82.3018 196.421 86.5928 206.818 95.1748C217.298 103.757 222.538 115.722 222.538 131.071C222.538 139.323 220.475 146.791 216.349 153.475C212.223 160.159 206.406 165.523 198.896 169.566C209.046 173.032 216.803 178.561 222.167 186.153C227.613 193.744 230.336 202.945 230.336 213.755C230.336 230.672 225.427 243.875 215.607 253.365C205.787 262.772 192.295 267.476 175.131 267.476C162.093 267.476 150.499 264.34 140.349 258.068V313H104.577V137.012C104.577 126.697 107.176 117.373 112.375 109.038C117.573 100.621 124.794 94.0608 134.036 89.3572C143.278 84.6536 153.428 82.3018 164.486 82.3018ZM186.766 133.794C186.766 127.027 184.703 121.581 180.577 117.455C176.534 113.329 171.17 111.266 164.486 111.266C157.472 111.266 151.695 113.618 147.157 118.322C142.618 122.943 140.349 129.338 140.349 137.507V231.456C147.115 236.242 156.028 238.635 167.085 238.635C175.502 238.635 182.186 236.283 187.137 231.58C192.089 226.793 194.564 220.687 194.564 213.26C194.564 204.348 192.295 197.416 187.756 192.465C183.3 187.432 176.699 184.915 167.952 184.915H155.945V158.797H165.6C179.711 158.302 186.766 149.968 186.766 133.794Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,15 +0,0 @@
<svg width="343" height="343" viewBox="0 0 343 343" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<rect x="141.421" y="31" width="200" height="200" transform="rotate(45 141.421 31)" fill="#01BE6E"/>
<path d="M137.926 182.464C128.751 173.507 120.668 165.642 116.08 147.51H148.194V133.965H116.298V116.051H102.535V134.184H70.4214V147.728H103.191C103.191 147.728 102.972 150.35 102.535 152.316C97.9475 170.23 92.486 181.59 70.4214 192.731L75.0091 206.276C95.9814 195.134 106.904 181.153 111.711 165.642C116.298 177.439 124.163 187.051 133.12 195.79L137.926 182.464Z" fill="white"/>
<path d="M180.307 138.551H161.956L129.842 228.775H143.605L152.781 201.686H189.482L198.658 228.775H212.421L180.307 138.551ZM157.368 188.142L171.132 152.095L184.895 188.36L157.368 188.142Z" fill="white"/>
<path d="M305.473 170.182L208.174 267.48C206.834 268.82 205.148 269.773 203.306 270.234L148.421 281.018L159.206 226.123C159.666 224.291 160.619 222.605 161.959 221.265L259.258 123.967L274.421 108.803L320.421 103.921V155.233L305.473 170.182Z" fill="#99AAB5"/>
<path d="M208.174 267.478L305.473 170.18L259.258 123.965L161.959 221.263C160.619 222.603 159.666 224.289 159.206 226.121L148.421 281.016L203.306 270.232C205.148 269.771 206.834 268.818 208.174 267.478ZM336.883 138.769C345.06 130.592 345.06 117.337 336.883 109.16L320.278 92.5542C312.1 84.3771 298.845 84.3771 290.668 92.5542L274.063 109.16L320.278 155.375L336.883 138.769Z" fill="#EA596E"/>
<path d="M305.473 170.182L208.174 267.48C206.834 268.82 205.148 269.773 203.306 270.234L148.421 281.018L159.206 226.123C159.666 224.291 160.619 222.605 161.959 221.265L259.258 123.967L305.473 170.182Z" fill="#FFCC4D"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="343" height="343" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -1,3 +0,0 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M30.9299 18.0767C30.9299 20.7484 29.4776 22.3521 26.3783 22.3521H21.2468V13.8981H26.3792C29.4776 13.8981 30.9299 15.5498 30.9299 18.0767ZM8 7L12.9681 13.9144V41.1006H21.2477V28.2293H23.2331L30.3031 41.1035H39.648L31.8041 27.5976C33.9941 27.0629 35.9365 25.7938 37.3097 24.0006C38.683 22.2073 39.4048 19.9973 39.3556 17.7364C39.3556 11.8093 35.192 7 26.8636 7H8Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

View File

@@ -0,0 +1 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="64.00001046823172" xmlns="http://www.w3.org/2000/svg" id="screenshot" version="1.1" viewBox="-0.000008942940667111543 -0.0000033745862566547657 64.00001046823172 64.00000545874563" height="64.00000545874563" style="-webkit-print-color-adjust: exact;"><g id="shape-d9b11490-3403-11ec-bc16-7b519797d558"><rect rx="0" ry="0" x="0" y="0" transform="matrix(1.0000000000000007,-8.726646259971662e-8,-1.5707963280665485e-7,1.0000000000000124,0.000005026548230091521,0.0000027925264056705146)" width="64" height="64" style="fill: rgb(255, 255, 255); fill-opacity: 1;"/></g></svg>

After

Width:  |  Height:  |  Size: 626 B

View File

@@ -0,0 +1 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="64.00001046823172" xmlns="http://www.w3.org/2000/svg" id="screenshot" version="1.1" viewBox="-0.000008942940667111543 -0.0000033745862566547657 64.00001046823172 64.00000545874563" height="64.00000545874563" style="-webkit-print-color-adjust: exact;"><g id="shape-d9b11490-3403-11ec-bc16-7b519797d558"><rect rx="0" ry="0" x="0" y="0" transform="matrix(1.0000000000000007,-8.726646259971662e-8,-1.5707963280665485e-7,1.0000000000000124,0.000005026548230091521,0.0000027925264056705146)" width="64" height="64" style="fill: rgb(255, 255, 255); fill-opacity: 1;"/></g></svg>

After

Width:  |  Height:  |  Size: 626 B

View File

@@ -0,0 +1 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="64.00001046823172" xmlns="http://www.w3.org/2000/svg" id="screenshot" version="1.1" viewBox="-0.000008942940667111543 -0.0000033745862566547657 64.00001046823172 64.00000545874563" height="64.00000545874563" style="-webkit-print-color-adjust: exact;"><g id="shape-d9b11490-3403-11ec-bc16-7b519797d558"><rect rx="0" ry="0" x="0" y="0" transform="matrix(1.0000000000000007,-8.726646259971662e-8,-1.5707963280665485e-7,1.0000000000000124,0.000005026548230091521,0.0000027925264056705146)" width="64" height="64" style="fill: rgb(255, 255, 255); fill-opacity: 1;"/></g></svg>

After

Width:  |  Height:  |  Size: 626 B

View File

@@ -0,0 +1 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="64.00001046823172" xmlns="http://www.w3.org/2000/svg" id="screenshot" version="1.1" viewBox="-0.000008942940667111543 -0.0000033745862566547657 64.00001046823172 64.00000545874563" height="64.00000545874563" style="-webkit-print-color-adjust: exact;"><g id="shape-d9b11490-3403-11ec-bc16-7b519797d558"><rect rx="0" ry="0" x="0" y="0" transform="matrix(1.0000000000000007,-8.726646259971662e-8,-1.5707963280665485e-7,1.0000000000000124,0.000005026548230091521,0.0000027925264056705146)" width="64" height="64" style="fill: rgb(255, 255, 255); fill-opacity: 1;"/></g></svg>

After

Width:  |  Height:  |  Size: 626 B

View File

@@ -0,0 +1 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="64.00001046823172" xmlns="http://www.w3.org/2000/svg" id="screenshot" version="1.1" viewBox="-0.000008942940667111543 -0.0000033745862566547657 64.00001046823172 64.00000545874563" height="64.00000545874563" style="-webkit-print-color-adjust: exact;"><g id="shape-d9b11490-3403-11ec-bc16-7b519797d558"><rect rx="0" ry="0" x="0" y="0" transform="matrix(1.0000000000000007,-8.726646259971662e-8,-1.5707963280665485e-7,1.0000000000000124,0.000005026548230091521,0.0000027925264056705146)" width="64" height="64" style="fill: rgb(255, 255, 255); fill-opacity: 1;"/></g></svg>

After

Width:  |  Height:  |  Size: 626 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chat" viewBox="0 0 16 16">
<path d="M2.678 11.894a1 1 0 0 1 .287.801 10.97 10.97 0 0 1-.398 2c1.395-.323 2.247-.697 2.634-.893a1 1 0 0 1 .71-.074A8.06 8.06 0 0 0 8 14c3.996 0 7-2.807 7-6 0-3.192-3.004-6-7-6S1 4.808 1 8c0 1.468.617 2.83 1.678 3.894zm-.493 3.905a21.682 21.682 0 0 1-.713.129c-.2.032-.352-.176-.273-.362a9.68 9.68 0 0 0 .244-.637l.003-.01c.248-.72.45-1.548.524-2.319C.743 11.37 0 9.76 0 8c0-3.866 3.582-7 8-7s8 3.134 8 7-3.582 7-8 7a9.06 9.06 0 0 1-2.347-.306c-.52.263-1.639.742-3.468 1.105z"/>
</svg>

After

Width:  |  Height:  |  Size: 613 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View File

@@ -0,0 +1,21 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="1266.1200469886633" xmlns="http://www.w3.org/2000/svg" id="screenshot" version="1.1" viewBox="-0.00002945408027699159 -0.0001327683537510893 1266.1200469886633 240.00014843559939" height="240.00014843559939" style="-webkit-print-color-adjust: exact;"><g id="shape-0d86b240-33f8-11ec-bc16-7b519797d558" width="1268" height="242" fill="none"><g id="shape-939dc8a0-33f8-11ec-bc16-7b519797d558"><g><path d="M14795 8655 c-472 -46 -855 -158 -1277 -372 -384 -195 -700 -454
-973 -798 -370 -468 -598 -1019 -691 -1675 -42 -299 -58 -819 -34 -1131 50
-637 207 -1176 477 -1634 415 -702 1027 -1168 1838 -1398 530 -151 1212 -178
1790 -72 782 144 1452 566 1915 1205 263 362 451 843 495 1261 l7 66 -953 5
c-644 4 -956 2 -961 -5 -3 -6 -9 -31 -13 -55 -17 -113 -95 -302 -174 -422 -56
-86 -187 -216 -277 -276 -199 -132 -398 -190 -694 -201 -277 -10 -504 36 -725
146 -461 230 -726 723 -786 1466 -15 190 -6 638 16 794 63 454 203 797 424
1046 212 238 488 376 831 416 143 16 386 7 513 -20 197 -42 402 -144 539 -269
123 -114 224 -276 281 -452 31 -94 41 -139 62 -272 l6 -38 956 0 955 0 -6 58
c-50 437 -133 735 -296 1067 -258 524 -661 930 -1195 1202 -365 186 -721 291
-1175 349 -175 22 -690 27 -875 9z M19190 5090 l0 -3490 945 0 945 0 0 1365 0
1365 1260 0 1260 0 0 -1365 0 -1365 940 0 940 0 0 3490 0 3490 -940 0 -940 0
0 -1365 0 -1365 -1260 0 -1260 0 0 1365 0 1365 -945 0 -945 0 0 -3490z M27365
5253 c-604 -1831 -1122 -3401 -1151 -3491 l-52 -162 1017 0 1017 0 179 592
c98 326 189 628 202 671 l24 77 1154 0 1154 0 24 -77 c13 -43 104 -345 202
-671 l179 -592 1017 0 1018 0 -14 43 c-19 57 -854 2589 -1639 4969 -355 1077
-646 1960 -646 1963 0 3 -582 5 -1293 5 l-1293 0 -1099 -3327z m2429 1390
c225 -747 677 -2250 682 -2268 l6 -25 -727 0 -727 0 6 23 c3 12 156 524 341
1137 185 613 338 1123 341 1133 4 12 16 17 39 17 23 0 35 -5 39 -17z M32960
7820 l0 -760 1050 0 1050 0 0 -2730 0 -2730 930 0 930 0 0 2730 0 2730 1050 0
1050 0 0 760 0 760 -3030 0 -3030 0 0 -760z" transform="translate(0, 0) scale(0.25, 0.25) translate(0.000000,960.000000) scale(0.100000,-0.100000)" fill="#ffffff" stroke="none"/></g></g></g></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

49
scripts/inject.js Normal file
View File

@@ -0,0 +1,49 @@
/* eslint-disable */
const { copy, remove, access, readFile, writeFile } = require("fs-extra");
const klaw = require("klaw");
let target = /__API_URL__/g;
let replacement = process.env.REVOLT_PUBLIC_URL;
let BUILD_DIRECTORY = "dist";
let OUT_DIRECTORY = "dist_injected";
if (typeof replacement === "undefined") {
console.error("No REVOLT_PUBLIC_URL specified in environment variables.");
process.exit(1);
}
(async () => {
console.log("Ensuring project has been built at least once.");
try {
await access(BUILD_DIRECTORY);
} catch (err) {
console.error("Build project at least once!");
return process.exit(1);
}
console.log("Determining if injected build already exists...");
try {
await access(OUT_DIRECTORY);
console.log("Deleting existing build...");
await remove(OUT_DIRECTORY);
} catch (err) {}
await copy(BUILD_DIRECTORY, OUT_DIRECTORY);
console.log("Processing bundles...");
for await (const file of klaw(OUT_DIRECTORY)) {
let path = file.path;
if (path.endsWith(".js")) {
let data = await readFile(path);
if (target.test(data)) {
console.log("Matched file", path);
let processed = data.toString().replace(target, replacement);
await writeFile(path, processed);
}
}
}
console.log("Complete.");
})();

0
publish.sh → scripts/publish.sh Normal file → Executable file
View File

39
scripts/setup_assets.js Normal file
View File

@@ -0,0 +1,39 @@
/* eslint-disable */
const { copy, remove, access } = require("fs-extra");
const { exec: cexec } = require("child_process");
const { resolve } = require("path");
let target = process.env.REVOLT_SASS;
let branch = process.env.REVOLT_SASS_BRANCH;
let DEFAULT_DIRECTORY = "public/assets_default";
let OUT_DIRECTORY = "public/assets";
function exec(command) {
return new Promise((fulfil, reject) => {
cexec(command, (err, stdout, stderr) => {
if (err) {
reject(err);
return;
}
fulfil({ stdout, stderr });
});
});
}
(async () => {
try {
await access(OUT_DIRECTORY);
if (process.argv[2] === "--check") return;
await remove(OUT_DIRECTORY);
} catch (err) {}
if (target) {
let arg = branch ? `-b ${branch} ` : "";
await exec(`git clone ${arg}${target} ${OUT_DIRECTORY}`);
await exec(`rm -rf ${resolve(OUT_DIRECTORY, ".git")}`);
} else {
await copy(DEFAULT_DIRECTORY, OUT_DIRECTORY);
}
})();

View File

@@ -1,3 +0,0 @@
<svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M290.947 209.226C290.947 227.612 280.944 238.648 259.595 238.648H224.247V180.471H259.601C280.944 180.471 290.947 191.837 290.947 209.226ZM133 133L167.222 180.583V367.669H224.254V279.094H237.93L286.63 367.689H351L296.969 274.746C312.054 271.066 325.434 262.333 334.893 249.993C344.353 237.652 349.325 222.444 348.986 206.885C348.986 166.096 320.306 133 262.938 133H167.222H133Z" fill="#FF4654" stroke="#FF4654" stroke-width="1.04306"/>
</svg>

Before

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

View File

@@ -1,4 +0,0 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="193.733" height="37.438" viewBox="0 0 193.733 37.438">
<path d="M23.393,1.382c0,2.787-1.52,4.46-4.764,4.46H13.258V-2.977H18.63C21.873-2.977,23.393-1.254,23.393,1.382Zm-24-11.555,5.2,7.213V25.4h8.666V11.973h2.078l7.4,13.43h9.781l-8.21-14.089A10.355,10.355,0,0,0,32.212,1.027c0-6.183-4.358-11.2-13.075-11.2Zm60.035,0H37.634V25.4H59.426V18.46H46.3v-7.8H57.906V3.966H46.3V-2.969H59.426Zm20.981,26.86-8.818-26.86H62.365L74.984,25.4H85.83L98.449-10.173H89.276Zm56.659-9.173c0-10.693-8.058-18.194-18.194-18.194-10.085,0-18.3,7.5-18.3,18.194a17.9,17.9,0,0,0,18.3,18.244A17.815,17.815,0,0,0,137.066,7.514Zm-27.62,0c0-6.335,3.649-10.338,9.426-10.338,5.676,0,9.376,4,9.376,10.338,0,6.233-3.7,10.338-9.376,10.338C113.095,17.852,109.446,13.747,109.446,7.514ZM141.88-10.173V25.4H161.9v-6.95H150.545V-10.173Zm22.248,7.2h9.426V25.4h8.666V-2.975h9.426v-7.2H164.128Z" transform="translate(1.586 11.18)" fill="#fff" stroke="#fff" stroke-width="1"/>
</svg>

Before

Width:  |  Height:  |  Size: 1008 B

View File

@@ -1,5 +1,6 @@
import { observer } from "mobx-react-lite";
import { useHistory } from "react-router-dom";
import { Channel } from "revolt.js";
import { Channel } from "revolt.js/dist/maps/Channels";
import styled from "styled-components";
import { Text } from "preact-i18n";
@@ -46,7 +47,7 @@ type Props = {
channel: Channel;
};
export default function AgeGate(props: Props) {
export default observer((props: Props) => {
const history = useHistory();
const [consent, setConsent] = useState(
getState().sectionToggle["nsfw"] ?? false,
@@ -67,6 +68,7 @@ export default function AgeGate(props: Props) {
return (
<Base>
<img
loading="eager"
src={"https://static.revolt.chat/emoji/mutant/26a0.svg"}
draggable={false}
/>
@@ -104,4 +106,4 @@ export default function AgeGate(props: Props) {
</div>
</Base>
);
}
});

View File

@@ -1,10 +1,10 @@
import { SYSTEM_USER_ID, User } from "revolt.js";
import { Channels } from "revolt.js/dist/api/objects";
import { Channel } from "revolt.js/dist/maps/Channels";
import { User } from "revolt.js/dist/maps/Users";
import styled, { css } from "styled-components";
import { StateUpdater, useContext, useState } from "preact/hooks";
import { StateUpdater, useState } from "preact/hooks";
import { AppContext } from "../../context/revoltjs/RevoltClient";
import { useClient } from "../../context/revoltjs/RevoltClient";
import { emojiDictionary } from "../../assets/emojis";
import ChannelIcon from "./ChannelIcon";
@@ -14,19 +14,19 @@ import UserIcon from "./user/UserIcon";
export type AutoCompleteState =
| { type: "none" }
| ({ selected: number; within: boolean } & (
| {
type: "emoji";
matches: string[];
}
| {
type: "user";
matches: User[];
}
| {
type: "channel";
matches: Channels.TextChannel[];
}
));
| {
type: "emoji";
matches: string[];
}
| {
type: "user";
matches: User[];
}
| {
type: "channel";
matches: Channel[];
}
));
export type SearchClues = {
users?: { type: "channel"; id: string } | { type: "all" };
@@ -52,7 +52,7 @@ export function useAutoComplete(
): AutoCompleteProps {
const [state, setState] = useState<AutoCompleteState>({ type: "none" });
const [focused, setFocused] = useState(false);
const client = useContext(AppContext);
const client = useClient();
function findSearchString(
el: HTMLTextAreaElement,
@@ -79,13 +79,15 @@ export function useAutoComplete(
if (current === ":" || current === "@" || current === "#") {
const search = content.slice(j + 1, content.length);
if (search.length > 0) {
const minLen = current === ":" ? 2 : 1
if (search.length >= minLen) {
return [
current === "#"
? "channel"
: current === ":"
? "emoji"
: "user",
? "emoji"
: "user",
search.toLowerCase(),
j + 1,
];
@@ -103,7 +105,7 @@ export function useAutoComplete(
const regex = new RegExp(search, "i");
if (type === "emoji") {
// ! FIXME: we should convert it to a Binary Search Tree and use that
// ! TODO: we should convert it to a Binary Search Tree and use that
const matches = Object.keys(emojiDictionary)
.filter((emoji: string) => emoji.match(regex))
.splice(0, 5);
@@ -127,7 +129,7 @@ export function useAutoComplete(
let users: User[] = [];
switch (searchClues.users.type) {
case "all":
users = client.users.toArray();
users = [...client.users.values()];
break;
case "channel": {
const channel = client.channels.get(
@@ -136,25 +138,21 @@ export function useAutoComplete(
switch (channel?.channel_type) {
case "Group":
case "DirectMessage":
users = client.users
.mapKeys(channel.recipients)
.filter(
(x) => typeof x !== "undefined",
) as User[];
users = channel.recipients!.filter(
(x) => typeof x !== "undefined",
) as User[];
break;
case "TextChannel":
const server = channel.server;
users = client.servers.members
.toArray()
.filter(
(x) => x._id.substr(0, 26) === server,
)
.map((x) =>
client.users.get(x._id.substr(26)),
)
.filter(
(x) => typeof x !== "undefined",
) as User[];
{
const server = channel.server_id;
users = [...client.members.keys()]
.map((x) => JSON.parse(x))
.filter((x) => x.server === server)
.map((x) => client.users.get(x.user))
.filter(
(x) => typeof x !== "undefined",
) as User[];
}
break;
default:
return;
@@ -162,13 +160,15 @@ export function useAutoComplete(
}
}
users = users.filter((x) => x._id !== SYSTEM_USER_ID);
users = users.filter(
(x) => x._id !== "00000000000000000000000000",
);
const matches = (
search.length > 0
? users.filter((user) =>
user.username.toLowerCase().match(regex),
)
user.username.toLowerCase().match(regex),
)
: users
)
.splice(0, 5)
@@ -192,16 +192,15 @@ export function useAutoComplete(
if (type === "channel" && searchClues?.channels) {
const channels = client.servers
.get(searchClues.channels.server)
?.channels.map((x) => client.channels.get(x))
.filter(
?.channels.filter(
(x) => typeof x !== "undefined",
) as Channels.TextChannel[];
) as Channel[];
const matches = (
search.length > 0
? channels.filter((channel) =>
channel.name.toLowerCase().match(regex),
)
channel.name!.toLowerCase().match(regex),
)
: channels
)
.splice(0, 5)
@@ -268,6 +267,7 @@ export function useAutoComplete(
function onClick(ev: JSX.TargetedMouseEvent<HTMLButtonElement>) {
ev.preventDefault();
selectCurrent(document.querySelector("#message")!);
setFocused(false);
}
function onKeyDown(e: KeyboardEvent) {
@@ -309,7 +309,7 @@ export function useAutoComplete(
function onKeyUp(e: KeyboardEvent) {
if (e.currentTarget !== null) {
// @ts-expect-error
// @ts-expect-error Type mis-match.
onChange(e);
}
}
@@ -396,6 +396,7 @@ export default function AutoComplete({
{state.type === "emoji" &&
state.matches.map((match, i) => (
<button
key={match}
className={i === state.selected ? "active" : ""}
onMouseEnter={() =>
(i !== state.selected || !state.within) &&
@@ -416,7 +417,7 @@ export default function AutoComplete({
<Emoji
emoji={
(emojiDictionary as Record<string, string>)[
match
match
]
}
size={20}
@@ -427,6 +428,7 @@ export default function AutoComplete({
{state.type === "user" &&
state.matches.map((match, i) => (
<button
key={match}
className={i === state.selected ? "active" : ""}
onMouseEnter={() =>
(i !== state.selected || !state.within) &&
@@ -451,6 +453,7 @@ export default function AutoComplete({
{state.type === "channel" &&
state.matches.map((match, i) => (
<button
key={match}
className={i === state.selected ? "active" : ""}
onMouseEnter={() =>
(i !== state.selected || !state.within) &&

View File

@@ -1,5 +1,6 @@
import { Hash, VolumeFull } from "@styled-icons/boxicons-regular";
import { Channels } from "revolt.js/dist/api/objects";
import { observer } from "mobx-react-lite";
import { Channel } from "revolt.js/dist/maps/Channels";
import { useContext } from "preact/hooks";
@@ -8,58 +9,65 @@ import { AppContext } from "../../context/revoltjs/RevoltClient";
import { ImageIconBase, IconBaseProps } from "./IconBase";
import fallback from "./assets/group.png";
interface Props
extends IconBaseProps<
Channels.GroupChannel | Channels.TextChannel | Channels.VoiceChannel
> {
interface Props extends IconBaseProps<Channel> {
isServerChannel?: boolean;
}
export default function ChannelIcon(
props: Props & Omit<JSX.HTMLAttributes<HTMLImageElement>, keyof Props>,
) {
const client = useContext(AppContext);
export default observer(
(
props: Props &
Omit<
JSX.HTMLAttributes<HTMLImageElement>,
keyof Props | "children" | "as"
>,
) => {
const client = useContext(AppContext);
const {
size,
target,
attachment,
isServerChannel: server,
animate,
children,
as,
...imgProps
} = props;
const iconURL = client.generateFileURL(
target?.icon ?? attachment,
{ max_side: 256 },
animate,
);
const isServerChannel =
server ||
(target &&
(target.channel_type === "TextChannel" ||
target.channel_type === "VoiceChannel"));
const {
size,
target,
attachment,
isServerChannel: server,
animate,
...imgProps
} = props;
const iconURL = client.generateFileURL(
target?.icon ?? attachment,
{ max_side: 256 },
animate,
);
const isServerChannel =
server ||
(target &&
(target.channel_type === "TextChannel" ||
target.channel_type === "VoiceChannel"));
if (typeof iconURL === "undefined") {
if (isServerChannel) {
if (target?.channel_type === "VoiceChannel") {
return <VolumeFull size={size} />;
if (typeof iconURL === "undefined") {
if (isServerChannel) {
if (target?.channel_type === "VoiceChannel") {
return <VolumeFull size={size} />;
}
return <Hash size={size} />;
}
return <Hash size={size} />;
}
}
return (
// ! fixme: replace fallback with <picture /> + <source />
<ImageIconBase
{...imgProps}
width={size}
height={size}
loading="lazy"
aria-hidden="true"
square={isServerChannel}
src={iconURL ?? fallback}
/>
);
}
// The border radius of the channel icon, if it's a server-channel it should be square (undefined).
let borderRadius: string | undefined = "--border-radius-channel-icon";
if (isServerChannel) {
borderRadius = undefined;
}
return (
// ! TODO: replace fallback with <picture /> + <source />
<ImageIconBase
{...imgProps}
width={size}
height={size}
loading="lazy"
aria-hidden="true"
borderRadius={borderRadius}
src={iconURL ?? fallback}
/>
);
},
);

View File

@@ -55,6 +55,7 @@ export default function Emoji({
return (
<img
alt={emoji}
loading="lazy"
className="emoji"
draggable={false}
src={parseEmoji(emoji)}
@@ -66,7 +67,7 @@ export default function Emoji({
}
export function generateEmoji(emoji: string) {
return `<img class="emoji" draggable="false" alt="${emoji}" src="${parseEmoji(
return `<img loading="lazy" class="emoji" draggable="false" alt="${emoji}" src="${parseEmoji(
emoji,
)}" />`;
}

View File

@@ -1,16 +1,22 @@
import { Attachment } from "revolt.js/dist/api/objects";
import { Attachment } from "revolt-api/types/Autumn";
import styled, { css } from "styled-components";
export interface IconBaseProps<T> {
target?: T;
url?: string;
attachment?: Attachment;
size: number;
hover?: boolean;
animate?: boolean;
}
interface IconModifiers {
square?: boolean;
/**
* If this is undefined or null then the icon defaults to square, else uses the CSS variable given.
*/
borderRadius?: string;
hover?: boolean;
}
export default styled.svg<IconModifiers>`
@@ -22,11 +28,19 @@ export default styled.svg<IconModifiers>`
object-fit: cover;
${(props) =>
!props.square &&
props.borderRadius &&
css`
border-radius: 50%;
border-radius: var(${props.borderRadius});
`}
}
${(props) =>
props.hover &&
css`
&:hover .icon {
filter: brightness(0.8);
}
`}
`;
export const ImageIconBase = styled.img<IconModifiers>`
@@ -34,8 +48,16 @@ export const ImageIconBase = styled.img<IconModifiers>`
object-fit: cover;
${(props) =>
!props.square &&
props.borderRadius &&
css`
border-radius: 50%;
border-radius: var(${props.borderRadius});
`}
${(props) =>
props.hover &&
css`
&:hover img {
filter: brightness(0.8);
}
`}
`;

View File

@@ -22,7 +22,7 @@ export function LocaleSelector(props: Props) {
{Object.keys(Languages).map((x) => {
const l = Languages[x as keyof typeof Languages];
return (
<option value={x}>
<option value={x} key={x}>
{l.emoji} {l.display}
</option>
);

View File

@@ -1,30 +1,28 @@
import { Check } from "@styled-icons/boxicons-regular";
import { Cog } from "@styled-icons/boxicons-solid";
import { observer } from "mobx-react-lite";
import { Link } from "react-router-dom";
import { Server } from "revolt.js/dist/api/objects";
import { ServerPermission } from "revolt.js/dist/api/permissions";
import { Server } from "revolt.js/dist/maps/Servers";
import styled from "styled-components";
import { HookContext, useServerPermission } from "../../context/revoltjs/hooks";
import { Text } from "preact-i18n";
import Header from "../ui/Header";
import IconButton from "../ui/IconButton";
import Tooltip from "./Tooltip";
interface Props {
server: Server;
ctx: HookContext;
}
const ServerName = styled.div`
flex-grow: 1;
`;
export default function ServerHeader({ server, ctx }: Props) {
const permissions = useServerPermission(server._id, ctx);
const bannerURL = ctx.client.servers.getBannerURL(
server._id,
{ width: 480 },
true,
);
export default observer(({ server }: Props) => {
const bannerURL = server.generateBannerURL({ width: 480 });
return (
<Header
@@ -34,8 +32,48 @@ export default function ServerHeader({ server, ctx }: Props) {
style={{
background: bannerURL ? `url('${bannerURL}')` : undefined,
}}>
{server.flags && server.flags & 1 ? (
<Tooltip
content={<Text id="app.special.server-badges.official" />}
placement={"bottom-start"}>
<svg width="20" height="20">
<image
xlinkHref="/assets/badges/verified.svg"
height="20"
width="20"
/>
<image
xlinkHref="/assets/badges/revolt_r.svg"
height="15"
width="15"
x="2"
y="3"
style={
"justify-content: center; align-items: center; filter: brightness(0);"
}
/>
</svg>
</Tooltip>
) : undefined}
{server.flags && server.flags & 2 ? (
<Tooltip
content={<Text id="app.special.server-badges.verified" />}
placement={"bottom-start"}>
<svg width="20" height="20">
<image
xlinkHref="/assets/badges/verified.svg"
height="20"
width="20"
/>
<foreignObject x="2" y="2" width="15" height="15">
<Check size={15} color="black" strokeWidth={8} />
</foreignObject>
</svg>
</Tooltip>
) : undefined}
<ServerName>{server.name}</ServerName>
{(permissions & ServerPermission.ManageServer) > 0 && (
{(server.permission & ServerPermission.ManageServer) > 0 && (
<div className="actions">
<Link to={`/server/${server._id}/settings`}>
<IconButton>
@@ -46,4 +84,4 @@ export default function ServerHeader({ server, ctx }: Props) {
)}
</Header>
);
}
});

View File

@@ -1,4 +1,5 @@
import { Server } from "revolt.js/dist/api/objects";
import { observer } from "mobx-react-lite";
import { Server } from "revolt.js/dist/maps/Servers";
import styled from "styled-components";
import { useContext } from "preact/hooks";
@@ -15,55 +16,54 @@ const ServerText = styled.div`
display: grid;
padding: 0.2em;
overflow: hidden;
border-radius: 50%;
place-items: center;
color: var(--foreground);
background: var(--primary-background);
border-radius: var(--border-radius-half);
`;
const fallback = "/assets/group.png";
export default function ServerIcon(
props: Props & Omit<JSX.HTMLAttributes<HTMLImageElement>, keyof Props>,
) {
const client = useContext(AppContext);
// const fallback = "/assets/group.png";
export default observer(
(
props: Props &
Omit<
JSX.HTMLAttributes<HTMLImageElement>,
keyof Props | "children" | "as"
>,
) => {
const client = useContext(AppContext);
const {
target,
attachment,
size,
animate,
server_name,
children,
as,
...imgProps
} = props;
const iconURL = client.generateFileURL(
target?.icon ?? attachment,
{ max_side: 256 },
animate,
);
const { target, attachment, size, animate, server_name, ...imgProps } =
props;
const iconURL = client.generateFileURL(
target?.icon ?? attachment,
{ max_side: 256 },
animate,
);
if (typeof iconURL === "undefined") {
const name = target?.name ?? server_name ?? "";
if (typeof iconURL === "undefined") {
const name = target?.name ?? server_name ?? "";
return (
<ServerText style={{ width: size, height: size }}>
{name
.split(" ")
.map((x) => x[0])
.filter((x) => typeof x !== "undefined")}
</ServerText>
);
}
return (
<ServerText style={{ width: size, height: size }}>
{name
.split(" ")
.map((x) => x[0])
.filter((x) => typeof x !== "undefined")}
</ServerText>
<ImageIconBase
{...imgProps}
width={size}
height={size}
borderRadius="--border-radius-server-icon"
src={iconURL}
loading="lazy"
aria-hidden="true"
/>
);
}
return (
<ImageIconBase
{...imgProps}
width={size}
height={size}
src={iconURL}
loading="lazy"
aria-hidden="true"
/>
);
}
},
);

View File

@@ -16,8 +16,8 @@ export default function Tooltip(props: Props) {
return (
<Tippy content={content} {...tippyProps}>
{/*
// @ts-expect-error */}
<div>{children}</div>
// @ts-expect-error Type mis-match. */}
<div style={`display: flex;`}>{children}</div>
</Tippy>
);
}
@@ -28,14 +28,14 @@ const PermissionTooltipBase = styled.div`
flex-direction: column;
span {
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
color: var(--secondary-foreground);
font-size: 11px;
}
code {
font-family: var(--monoscape-font);
font-family: var(--monospace-font);
}
`;

View File

@@ -1,4 +1,5 @@
import { Download } from "@styled-icons/boxicons-regular";
/* eslint-disable react-hooks/rules-of-hooks */
import { Download, CloudDownload } from "@styled-icons/boxicons-regular";
import { useContext, useEffect, useState } from "preact/hooks";
@@ -9,11 +10,16 @@ import { ThemeContext } from "../../context/Theme";
import IconButton from "../ui/IconButton";
import { updateSW } from "../../main";
import Tooltip from "./Tooltip";
let pendingUpdate = false;
internalSubscribe("PWA", "update", () => (pendingUpdate = true));
export default function UpdateIndicator() {
interface Props {
style: "titlebar" | "channel";
}
export default function UpdateIndicator({ style }: Props) {
const [pending, setPending] = useState(pendingUpdate);
useEffect(() => {
@@ -23,6 +29,22 @@ export default function UpdateIndicator() {
if (!pending) return null;
const theme = useContext(ThemeContext);
if (style === "titlebar") {
return (
<div class="actions">
<Tooltip
content="A new update is available!"
placement="bottom">
<div onClick={() => updateSW(true)}>
<CloudDownload size={22} color={theme.success} />
</div>
</Tooltip>
</div>
);
}
if (window.isNative) return null;
return (
<IconButton onClick={() => updateSW(true)}>
<Download size={22} color={theme.success} />

View File

@@ -1,13 +1,16 @@
import { observer } from "mobx-react-lite";
import { Message as MessageObject } from "revolt.js/dist/maps/Messages";
import { attachContextMenu } from "preact-context-menu";
import { memo } from "preact/compat";
import { useContext } from "preact/hooks";
import { useState } from "preact/hooks";
import { internalEmit } from "../../../lib/eventEmitter";
import { QueuedMessage } from "../../../redux/reducers/queue";
import { useIntermediate } from "../../../context/intermediate/Intermediate";
import { AppContext } from "../../../context/revoltjs/RevoltClient";
import { useUser } from "../../../context/revoltjs/hooks";
import { MessageObject } from "../../../context/revoltjs/util";
import { useClient } from "../../../context/revoltjs/RevoltClient";
import Overline from "../../ui/Overline";
@@ -23,6 +26,7 @@ import MessageBase, {
import Attachment from "./attachments/Attachment";
import { MessageReply } from "./attachments/MessageReply";
import Embed from "./embed/Embed";
import InviteList from "./embed/EmbedInvite";
interface Props {
attachContext?: boolean;
@@ -32,105 +36,149 @@ interface Props {
contrast?: boolean;
content?: Children;
head?: boolean;
hideReply?: boolean;
}
function Message({
highlight,
attachContext,
message,
contrast,
content: replacement,
head: preferHead,
queued,
}: Props) {
// TODO: Can improve re-renders here by providing a list
// TODO: of dependencies. We only need to update on u/avatar.
const user = useUser(message.author);
const client = useContext(AppContext);
const { openScreen } = useIntermediate();
const Message = observer(
({
highlight,
attachContext,
message,
contrast,
content: replacement,
head: preferHead,
queued,
hideReply,
}: Props) => {
const client = useClient();
const user = message.author;
const content = message.content as string;
const head = preferHead || (message.replies && message.replies.length > 0);
const { openScreen } = useIntermediate();
// ! FIXME: tell fatal to make this type generic
// bree: Fatal please...
const userContext = attachContext
? (attachContextMenu("Menu", {
user: message.author,
contextualChannel: message.channel,
}) as any)
: undefined;
const content = message.content as string;
const head =
preferHead || (message.reply_ids && message.reply_ids.length > 0);
const openProfile = () =>
openScreen({ id: "profile", user_id: message.author });
// ! TODO: tell fatal to make this type generic
// bree: Fatal please...
const userContext = attachContext
? (attachContextMenu("Menu", {
user: message.author_id,
contextualChannel: message.channel_id,
// eslint-disable-next-line
}) as any)
: undefined;
return (
<div id={message._id}>
{message.replies?.map((message_id, index) => (
<MessageReply
index={index}
id={message_id}
channel={message.channel}
/>
))}
<MessageBase
highlight={highlight}
head={head && !(message.replies && message.replies.length > 0)}
contrast={contrast}
sending={typeof queued !== "undefined"}
mention={message.mentions?.includes(client.user!._id)}
failed={typeof queued?.error !== "undefined"}
onContextMenu={
attachContext
? attachContextMenu("Menu", {
message,
contextualChannel: message.channel,
queued,
})
: undefined
}>
<MessageInfo>
{head ? (
<UserIcon
target={user}
size={36}
onContextMenu={userContext}
onClick={openProfile}
const openProfile = () =>
openScreen({ id: "profile", user_id: message.author_id });
const handleUserClick = (e: MouseEvent) => {
if (e.shiftKey && user?._id) {
internalEmit(
"MessageBox",
"append",
`<@${user._id}>`,
"mention",
);
} else {
openProfile();
}
};
// ! FIXME(?): animate on hover
const [animate, setAnimate] = useState(false);
return (
<div id={message._id}>
{!hideReply &&
message.reply_ids?.map((message_id, index) => (
<MessageReply
key={message_id}
index={index}
id={message_id}
channel={message.channel!}
parent_mentions={message.mention_ids ?? []}
/>
) : (
<MessageDetail message={message} position="left" />
)}
</MessageInfo>
<MessageContent>
{head && (
<span className="detail">
<Username
className="author"
user={user}
))}
<MessageBase
highlight={highlight}
head={
hideReply
? false
: (head &&
!(
message.reply_ids &&
message.reply_ids.length > 0
)) ??
false
}
contrast={contrast}
sending={typeof queued !== "undefined"}
mention={message.mention_ids?.includes(client.user!._id)}
failed={typeof queued?.error !== "undefined"}
onContextMenu={
attachContext
? attachContextMenu("Menu", {
message,
contextualChannel: message.channel_id,
queued,
})
: undefined
}
onMouseEnter={() => setAnimate(true)}
onMouseLeave={() => setAnimate(false)}>
<MessageInfo>
{head ? (
<UserIcon
url={message.generateMasqAvatarURL()}
target={user}
size={36}
onContextMenu={userContext}
onClick={openProfile}
onClick={handleUserClick}
animate={animate}
showServerIdentity
/>
<MessageDetail message={message} position="top" />
</span>
)}
{replacement ?? <Markdown content={content} />}
{queued?.error && (
<Overline type="error" error={queued.error} />
)}
{message.attachments?.map((attachment, index) => (
<Attachment
key={index}
attachment={attachment}
hasContent={index > 0 || content.length > 0}
/>
))}
{message.embeds?.map((embed, index) => (
<Embed key={index} embed={embed} />
))}
</MessageContent>
</MessageBase>
</div>
);
}
) : (
<MessageDetail message={message} position="left" />
)}
</MessageInfo>
<MessageContent>
{head && (
<span className="detail">
<Username
user={user}
className="author"
showServerIdentity
onClick={handleUserClick}
onContextMenu={userContext}
masquerade={message.masquerade!}
/>
<MessageDetail
message={message}
position="top"
/>
</span>
)}
{replacement ?? <Markdown content={content} />}
{!queued && <InviteList message={message} />}
{queued?.error && (
<Overline type="error" error={queued.error} />
)}
{message.attachments?.map((attachment, index) => (
<Attachment
key={index}
attachment={attachment}
hasContent={index > 0 || content.length > 0}
/>
))}
{message.embeds?.map((embed, index) => (
<Embed key={index} embed={embed} />
))}
</MessageContent>
</MessageBase>
</div>
);
},
);
export default memo(Message);

View File

@@ -1,12 +1,14 @@
import { observer } from "mobx-react-lite";
import { Message } from "revolt.js/dist/maps/Messages";
import styled, { css, keyframes } from "styled-components";
import { decodeTime } from "ulid";
import { Text } from "preact-i18n";
import { useDictionary } from "../../../lib/i18n";
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
import { dayjs } from "../../../context/Locale";
import { MessageObject } from "../../../context/revoltjs/util";
import Tooltip from "../Tooltip";
@@ -31,7 +33,13 @@ export default styled.div<BaseMessageProps>`
overflow: none;
padding: 0.125rem;
flex-direction: row;
padding-right: 16px;
padding-inline-end: 16px;
${() =>
isTouchscreenDevice &&
css`
user-select: none;
`}
${(props) =>
props.contrast &&
@@ -89,12 +97,20 @@ export default styled.div<BaseMessageProps>`
gap: 8px;
display: flex;
align-items: center;
flex-shrink: 0;
}
.author {
overflow: hidden;
cursor: pointer;
font-weight: 600 !important;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
white-space: normal;
&:hover {
text-decoration: underline;
}
@@ -111,6 +127,10 @@ export default styled.div<BaseMessageProps>`
time {
opacity: 1;
}
.system-message-icon {
display: none;
}
}
`;
@@ -165,6 +185,13 @@ export const MessageInfo = styled.div`
.header {
cursor: pointer;
}
.systemIcon {
height: 1.33em;
width: 1.33em;
margin-right: 0.5em;
color: var(--tertiary-foreground);
}
`;
export const MessageContent = styled.div`
@@ -172,12 +199,13 @@ export const MessageContent = styled.div`
flex-grow: 1;
display: flex;
// overflow: hidden;
font-size: var(--text-size);
flex-direction: column;
justify-content: center;
font-size: var(--text-size);
`;
export const DetailBase = styled.div`
flex-shrink: 0;
gap: 4px;
font-size: 10px;
display: inline-flex;
@@ -192,57 +220,54 @@ export const DetailBase = styled.div`
}
`;
export function MessageDetail({
message,
position,
}: {
message: MessageObject;
position: "left" | "top";
}) {
const dict = useDictionary();
export const MessageDetail = observer(
({ message, position }: { message: Message; position: "left" | "top" }) => {
const dict = useDictionary();
if (position === "left") {
if (message.edited) {
if (position === "left") {
if (message.edited) {
return (
<>
<time className="copyTime">
<i className="copyBracket">[</i>
{dayjs(decodeTime(message._id)).format(
dict.dayjs?.timeFormat,
)}
<i className="copyBracket">]</i>
</time>
<span className="edited">
<Tooltip
content={dayjs(message.edited).format("LLLL")}>
<Text id="app.main.channel.edited" />
</Tooltip>
</span>
</>
);
}
return (
<>
<time className="copyTime">
<time>
<i className="copyBracket">[</i>
{dayjs(decodeTime(message._id)).format(
dict.dayjs.timeFormat,
dict.dayjs?.timeFormat,
)}
<i className="copyBracket">]</i>
</time>
<span className="edited">
<Tooltip content={dayjs(message.edited).format("LLLL")}>
<Text id="app.main.channel.edited" />
</Tooltip>
</span>
</>
);
}
return (
<>
<time>
<i className="copyBracket">[</i>
{dayjs(decodeTime(message._id)).format(
dict.dayjs.timeFormat,
)}
<i className="copyBracket">]</i>
</time>
</>
);
}
return (
<DetailBase>
<time>{dayjs(decodeTime(message._id)).calendar()}</time>
{message.edited && (
<Tooltip content={dayjs(message.edited).format("LLLL")}>
<span className="edited">
<Text id="app.main.channel.edited" />
</span>
</Tooltip>
)}
</DetailBase>
);
}
return (
<DetailBase>
<time>{dayjs(decodeTime(message._id)).calendar()}</time>
{message.edited && (
<Tooltip content={dayjs(message.edited).format("LLLL")}>
<span className="edited">
<Text id="app.main.channel.edited" />
</span>
</Tooltip>
)}
</DetailBase>
);
},
);

View File

@@ -1,9 +1,9 @@
import { Send, HappyAlt, ShieldX } from "@styled-icons/boxicons-solid";
import { Styleshare } from "@styled-icons/simple-icons";
import { Send, ShieldX } from "@styled-icons/boxicons-solid";
import Axios, { CancelTokenSource } from "axios";
import { Channel } from "revolt.js";
import { observer } from "mobx-react-lite";
import { ChannelPermission } from "revolt.js/dist/api/permissions";
import styled from "styled-components";
import { Channel } from "revolt.js/dist/maps/Channels";
import styled, { css } from "styled-components";
import { ulid } from "ulid";
import { Text } from "preact-i18n";
@@ -16,7 +16,7 @@ import { internalEmit, internalSubscribe } from "../../../lib/eventEmitter";
import { useTranslation } from "../../../lib/i18n";
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
import {
SingletonMessageRenderer,
getRenderer,
SMOOTH_SCROLL_ON_RECEIVE,
} from "../../../lib/renderer/Singleton";
@@ -31,12 +31,10 @@ import {
uploadFile,
} from "../../../context/revoltjs/FileUploads";
import { AppContext } from "../../../context/revoltjs/RevoltClient";
import { useChannelPermission } from "../../../context/revoltjs/hooks";
import { takeError } from "../../../context/revoltjs/util";
import IconButton from "../../ui/IconButton";
import { PluginSingleton } from "../../../plugins";
import AutoComplete, { useAutoComplete } from "../AutoComplete";
import { PermissionTooltip } from "../Tooltip";
import FilePreview from "./bars/FilePreview";
@@ -101,17 +99,22 @@ const Action = styled.div`
padding: 12px;
}
.mobile {
@media (pointer: fine) {
display: none;
}
}
${() =>
!isTouchscreenDevice &&
css`
.mobile {
display: none;
}
`}
`;
// For sed replacement
const RE_SED = new RegExp("^s/([^])*/([^])*$");
// ! FIXME: add to app config and load from app config
export const CAN_UPLOAD_AT_ONCE = 4;
export default function MessageBox({ channel }: Props) {
export default observer(({ channel }: Props) => {
const [draft, setDraft] = useState(getState().drafts[channel._id] ?? "");
const [uploadState, setUploadState] = useState<UploadState>({
@@ -124,8 +127,9 @@ export default function MessageBox({ channel }: Props) {
const client = useContext(AppContext);
const translate = useTranslation();
const permissions = useChannelPermission(channel._id);
if (!(permissions & ChannelPermission.SendMessage)) {
const renderer = getRenderer(channel);
if (!(channel.permission & ChannelPermission.SendMessage)) {
return (
<Base>
<Blocked>
@@ -144,22 +148,25 @@ export default function MessageBox({ channel }: Props) {
);
}
function setMessage(content?: string) {
setDraft(content ?? "");
const setMessage = useCallback(
(content?: string) => {
setDraft(content ?? "");
if (content) {
dispatch({
type: "SET_DRAFT",
channel: channel._id,
content,
});
} else {
dispatch({
type: "CLEAR_DRAFT",
channel: channel._id,
});
}
}
if (content) {
dispatch({
type: "SET_DRAFT",
channel: channel._id,
content,
});
} else {
dispatch({
type: "CLEAR_DRAFT",
channel: channel._id,
});
}
},
[channel._id],
);
useEffect(() => {
function append(content: string, action: "quote" | "mention") {
@@ -178,59 +185,99 @@ export default function MessageBox({ channel }: Props) {
}
}
return internalSubscribe("MessageBox", "append", append);
}, [draft]);
return internalSubscribe(
"MessageBox",
"append",
append as (...args: unknown[]) => void,
);
}, [draft, setMessage]);
async function send() {
if (uploadState.type === "uploading" || uploadState.type === "sending")
return;
const content = draft?.trim() ?? "";
const target = { content };
if (PluginSingleton.emit("Message:Send", target)) return;
if (uploadState.type === "attached") return sendFile(target.content);
if (target.content.length === 0) return;
if (uploadState.type === "attached") return sendFile(content);
if (content.length === 0) return;
stopTyping();
setMessage();
setReplies([]);
playSound("outbound");
const nonce = ulid();
dispatch({
type: "QUEUE_ADD",
nonce,
channel: channel._id,
message: {
_id: nonce,
channel: channel._id,
author: client.user!._id,
content: target.content,
replies,
},
});
// sed style message editing.
// If the user types for example `s/abc/def`, the string "abc"
// will be replaced with "def" in their last sent message.
if (RE_SED.test(content)) {
renderer.messages.reverse();
const msg = renderer.messages.find(
(msg) => msg.author_id === client.user!._id,
);
renderer.messages.reverse();
defer(() =>
SingletonMessageRenderer.jumpToBottom(
channel._id,
SMOOTH_SCROLL_ON_RECEIVE,
),
);
if (msg) {
// eslint-disable-next-line prefer-const
let [_, toReplace, newText, flags] = content.split(/\//);
if (toReplace == "*") toReplace = msg.content.toString();
const newContent =
toReplace == ""
? msg.content.toString() + newText
: msg.content
.toString()
.replace(new RegExp(toReplace, flags), newText);
if (newContent != msg.content) {
if (newContent.length == 0) {
msg.delete().catch(console.error);
} else {
msg.edit({
content: newContent.substr(0, 2000),
})
.then(() =>
defer(() =>
renderer.jumpToBottom(
SMOOTH_SCROLL_ON_RECEIVE,
),
),
)
.catch(console.error);
}
}
}
} else {
playSound("outbound");
try {
await client.channels.sendMessage(channel._id, {
content: target.content,
nonce,
replies,
});
} catch (error) {
dispatch({
type: "QUEUE_FAIL",
error: takeError(error),
type: "QUEUE_ADD",
nonce,
channel: channel._id,
message: {
_id: nonce,
channel: channel._id,
author: client.user!._id,
content,
replies,
},
});
defer(() => renderer.jumpToBottom(SMOOTH_SCROLL_ON_RECEIVE));
try {
await channel.sendMessage({
content,
nonce,
replies,
});
} catch (error) {
dispatch({
type: "QUEUE_FAIL",
error: takeError(error),
nonce,
});
}
}
}
@@ -271,7 +318,8 @@ export default function MessageBox({ channel }: Props) {
);
}
} catch (err) {
if (err?.message === "cancel") {
// eslint-disable-next-line
if ((err as any)?.message === "cancel") {
setUploadState({
type: "attached",
files,
@@ -294,7 +342,7 @@ export default function MessageBox({ channel }: Props) {
const nonce = ulid();
try {
await client.channels.sendMessage(channel._id, {
await channel.sendMessage({
content,
nonce,
replies,
@@ -329,7 +377,7 @@ export default function MessageBox({ channel }: Props) {
const ws = client.websocket;
if (ws.connected) {
setTyping(+new Date() + 4000);
setTyping(+new Date() + 2500);
ws.send({
type: "BeginTyping",
channel: channel._id,
@@ -350,9 +398,12 @@ export default function MessageBox({ channel }: Props) {
}
}
const debouncedStopTyping = useCallback(debounce(stopTyping, 1000), [
channel._id,
]);
// TODO: change to useDebounceCallback
// eslint-disable-next-line
const debouncedStopTyping = useCallback(
debounce(stopTyping as (...args: unknown[]) => void, 1000),
[channel._id],
);
const {
onChange,
onKeyUp,
@@ -364,7 +415,7 @@ export default function MessageBox({ channel }: Props) {
users: { type: "channel", id: channel._id },
channels:
channel.channel_type === "TextChannel"
? { server: channel.server }
? { server: channel.server_id! }
: undefined,
});
@@ -402,12 +453,12 @@ export default function MessageBox({ channel }: Props) {
}}
/>
<ReplyBar
channel={channel._id}
channel={channel}
replies={replies}
setReplies={setReplies}
/>
<Base>
{permissions & ChannelPermission.UploadFiles ? (
{channel.permission & ChannelPermission.UploadFiles ? (
<Action>
<FileUploader
size={24}
@@ -450,10 +501,16 @@ export default function MessageBox({ channel }: Props) {
hideBorder
maxRows={20}
id="message"
maxLength={2000}
onKeyUp={onKeyUp}
value={draft ?? ""}
padding="var(--message-box-padding)"
onKeyDown={(e) => {
if (e.ctrlKey && e.key === "Enter") {
e.preventDefault();
return send();
}
if (onKeyDown(e)) return;
if (
@@ -467,6 +524,7 @@ export default function MessageBox({ channel }: Props) {
if (
!e.shiftKey &&
!e.isComposing &&
e.key === "Enter" &&
!isTouchscreenDevice
) {
@@ -474,19 +532,34 @@ export default function MessageBox({ channel }: Props) {
return send();
}
if (e.key === "Escape") {
if (replies.length > 0) {
setReplies(replies.slice(0, -1));
} else if (
uploadState.type === "attached" &&
uploadState.files.length > 0
) {
setUploadState({
type:
uploadState.files.length > 1
? "attached"
: "none",
files: uploadState.files.slice(0, -1),
});
}
}
debouncedStopTyping(true);
}}
placeholder={
channel.channel_type === "DirectMessage"
? translate("app.main.channel.message_who", {
person: client.users.get(
client.channels.getRecipient(channel._id),
)?.username,
person: channel.recipient?.username,
})
: channel.channel_type === "SavedMessages"
? translate("app.main.channel.message_saved")
: translate("app.main.channel.message_where", {
channel_name: channel.name,
channel_name: channel.name ?? undefined,
})
}
disabled={
@@ -515,4 +588,4 @@ export default function MessageBox({ channel }: Props) {
</Base>
</>
);
}
});

View File

@@ -1,13 +1,24 @@
import { User } from "revolt.js";
import {
InfoCircle,
UserPlus,
UserMinus,
ArrowToRight,
ArrowToLeft,
UserX,
ShieldX,
EditAlt,
Edit,
MessageSquareEdit,
} from "@styled-icons/boxicons-solid";
import { observer } from "mobx-react-lite";
import { SystemMessage as SystemMessageI } from "revolt-api/types/Channels";
import { Message } from "revolt.js/dist/maps/Messages";
import styled from "styled-components";
import { attachContextMenu } from "preact-context-menu";
import { TextReact } from "../../../lib/i18n";
import { useForceUpdate, useUser } from "../../../context/revoltjs/hooks";
import { MessageObject } from "../../../context/revoltjs/util";
import UserShort from "../user/UserShort";
import MessageBase, { MessageDetail, MessageInfo } from "./MessageBase";
@@ -20,151 +31,109 @@ const SystemContent = styled.div`
flex-direction: row;
`;
type SystemMessageParsed =
| { type: "text"; content: string }
| { type: "user_added"; user: User; by: User }
| { type: "user_remove"; user: User; by: User }
| { type: "user_joined"; user: User }
| { type: "user_left"; user: User }
| { type: "user_kicked"; user: User }
| { type: "user_banned"; user: User }
| { type: "channel_renamed"; name: string; by: User }
| { type: "channel_description_changed"; by: User }
| { type: "channel_icon_changed"; by: User };
interface Props {
attachContext?: boolean;
message: MessageObject;
message: Message;
highlight?: boolean;
hideInfo?: boolean;
}
export function SystemMessage({
attachContext,
message,
highlight,
hideInfo,
}: Props) {
const ctx = useForceUpdate();
const iconDictionary = {
user_added: UserPlus,
user_remove: UserMinus,
user_joined: ArrowToRight,
user_left: ArrowToLeft,
user_kicked: UserX,
user_banned: ShieldX,
channel_renamed: EditAlt,
channel_description_changed: Edit,
channel_icon_changed: MessageSquareEdit,
text: InfoCircle,
};
let data: SystemMessageParsed;
const content = message.content;
if (typeof content === "object") {
switch (content.type) {
export const SystemMessage = observer(
({ attachContext, message, highlight, hideInfo }: Props) => {
const data = message.asSystemMessage;
const SystemMessageIcon =
iconDictionary[data.type as SystemMessageI["type"]] ?? InfoCircle;
let children;
switch (data.type) {
case "text":
data = content;
children = <span>{data.content}</span>;
break;
case "user_added":
case "user_remove":
data = {
type: content.type,
user: useUser(content.id, ctx) as User,
by: useUser(content.by, ctx) as User,
};
children = (
<TextReact
id={`app.main.channel.system.${
data.type === "user_added"
? "added_by"
: "removed_by"
}`}
fields={{
user: <UserShort user={data.user} />,
other_user: <UserShort user={data.by} />,
}}
/>
);
break;
case "user_joined":
case "user_left":
case "user_kicked":
case "user_banned":
data = {
type: content.type,
user: useUser(content.id, ctx) as User,
};
children = (
<TextReact
id={`app.main.channel.system.${data.type}`}
fields={{
user: <UserShort user={data.user} />,
}}
/>
);
break;
case "channel_renamed":
data = {
type: "channel_renamed",
name: content.name,
by: useUser(content.by, ctx) as User,
};
children = (
<TextReact
id={`app.main.channel.system.channel_renamed`}
fields={{
user: <UserShort user={data.by} />,
name: <b>{data.name}</b>,
}}
/>
);
break;
case "channel_description_changed":
case "channel_icon_changed":
data = {
type: content.type,
by: useUser(content.by, ctx) as User,
};
children = (
<TextReact
id={`app.main.channel.system.${data.type}`}
fields={{
user: <UserShort user={data.by} />,
}}
/>
);
break;
default:
data = { type: "text", content: JSON.stringify(content) };
}
} else {
data = { type: "text", content };
}
let children;
switch (data.type) {
case "text":
children = <span>{data.content}</span>;
break;
case "user_added":
case "user_remove":
children = (
<TextReact
id={`app.main.channel.system.${
data.type === "user_added" ? "added_by" : "removed_by"
}`}
fields={{
user: <UserShort user={data.user} />,
other_user: <UserShort user={data.by} />,
}}
/>
);
break;
case "user_joined":
case "user_left":
case "user_kicked":
case "user_banned":
children = (
<TextReact
id={`app.main.channel.system.${data.type}`}
fields={{
user: <UserShort user={data.user} />,
}}
/>
);
break;
case "channel_renamed":
children = (
<TextReact
id={`app.main.channel.system.channel_renamed`}
fields={{
user: <UserShort user={data.by} />,
name: <b>{data.name}</b>,
}}
/>
);
break;
case "channel_description_changed":
case "channel_icon_changed":
children = (
<TextReact
id={`app.main.channel.system.${data.type}`}
fields={{
user: <UserShort user={data.by} />,
}}
/>
);
break;
}
return (
<MessageBase
highlight={highlight}
onContextMenu={
attachContext
? attachContextMenu("Menu", {
message,
contextualChannel: message.channel,
})
: undefined
}>
{!hideInfo && (
<MessageInfo>
<MessageDetail message={message} position="left" />
</MessageInfo>
)}
<SystemContent>{children}</SystemContent>
</MessageBase>
);
}
return (
<MessageBase
highlight={highlight}
onContextMenu={
attachContext
? attachContextMenu("Menu", {
message,
contextualChannel: message.channel,
})
: undefined
}>
{!hideInfo && (
<MessageInfo>
<MessageDetail message={message} position="left" />
<SystemMessageIcon className="systemIcon" />
</MessageInfo>
)}
<SystemContent>{children}</SystemContent>
</MessageBase>
);
},
);

View File

@@ -3,7 +3,7 @@
grid-auto-flow: row dense;
grid-auto-columns: min(100%, var(--attachment-max-width));
margin: .125rem 0 .125rem;
margin: 0.125rem 0 0.125rem;
width: max-content;
max-width: 100%;
@@ -56,7 +56,7 @@
}
pre code {
font-family: var(--monoscape-font), sans-serif;
font-family: var(--monospace-font), sans-serif;
}
&[data-loading="true"] {
@@ -84,6 +84,18 @@
}
}
.container, .attachment, .image {
.container,
.attachment,
.image {
border-radius: var(--border-radius);
}
.image {
cursor: pointer;
width: 100%;
height: 100%;
&.loading {
background: var(--background);
}
}

View File

@@ -1,7 +1,8 @@
import { Attachment as AttachmentRJS } from "revolt.js/dist/api/objects";
import { Attachment as AttachmentI } from "revolt-api/types/Autumn";
import styles from "./Attachment.module.scss";
import classNames from "classnames";
import { attachContextMenu } from "preact-context-menu";
import { useContext, useState } from "preact/hooks";
import { useIntermediate } from "../../../../context/intermediate/Intermediate";
@@ -9,11 +10,12 @@ import { AppContext } from "../../../../context/revoltjs/RevoltClient";
import AttachmentActions from "./AttachmentActions";
import { SizedGrid } from "./Grid";
import ImageFile from "./ImageFile";
import Spoiler from "./Spoiler";
import TextFile from "./TextFile";
interface Props {
attachment: AttachmentRJS;
attachment: AttachmentI;
hasContent: boolean;
}
@@ -21,7 +23,6 @@ const MAX_ATTACHMENT_WIDTH = 480;
export default function Attachment({ attachment, hasContent }: Props) {
const client = useContext(AppContext);
const { openScreen } = useIntermediate();
const { filename, metadata } = attachment;
const [spoiler, setSpoiler] = useState(filename.startsWith("SPOILER_"));
@@ -37,21 +38,17 @@ export default function Attachment({ attachment, hasContent }: Props) {
<SizedGrid
width={metadata.width}
height={metadata.height}
onContextMenu={attachContextMenu("Menu", {
attachment: attachment,
})}
className={classNames({
[styles.margin]: hasContent,
spoiler,
})}>
<img
src={url}
alt={filename}
className={styles.image}
loading="lazy"
onClick={() =>
openScreen({ id: "image_viewer", attachment })
}
onMouseDown={(ev) =>
ev.button === 1 && window.open(url, "_blank")
}
<ImageFile
attachment={attachment}
width={metadata.width}
height={metadata.height}
/>
{spoiler && <Spoiler set={setSpoiler} />}
</SizedGrid>

View File

@@ -5,7 +5,7 @@ import {
Headphone,
Video,
} from "@styled-icons/boxicons-regular";
import { Attachment } from "revolt.js/dist/api/objects";
import { Attachment } from "revolt-api/types/Autumn";
import styles from "./AttachmentActions.module.scss";
import classNames from "classnames";

View File

@@ -2,26 +2,54 @@ import styled from "styled-components";
import { Children } from "../../../../types/Preact";
const Grid = styled.div`
display: grid;
overflow: hidden;
const Grid = styled.div<{ width: number; height: number }>`
--width: ${props => props.width}px;
--height: ${props => props.height}px;
max-width: min(var(--attachment-max-width), 100%, var(--width));
max-height: min(var(--attachment-max-height), var(--height));
aspect-ratio: var(--aspect-ratio);
display: grid;
aspect-ratio: ${(props) => props.width} / ${(props) => props.height};
max-width: min(var(--width), var(--attachment-max-width));
max-height: min(var(--height), var(--attachment-max-height));
// This is a hack for browsers not supporting aspect-ratio.
// Stolen from https://codepen.io/una/pen/BazyaOM.
@supports not (
aspect-ratio: ${(props) => props.width} / ${(props) => props.height}
) {
div::before {
float: left;
padding-top: ${(props) => (props.height / props.width) * 100}%;
content: "";
}
div::after {
display: block;
content: "";
clear: both;
}
}
img,
video {
min-width: 100%;
min-height: 100%;
grid-area: 1 / 1;
width: auto;
height: auto;
display: block;
max-width: 100%;
max-height: 100%;
grid-area: 1 / 1;
overflow: hidden;
object-fit: contain;
// It's something
object-position: left;
}
video {
width: 100%;
height: 100%;
}
&.spoiler {
@@ -40,24 +68,16 @@ type Props = Omit<
JSX.HTMLAttributes<HTMLDivElement>,
"children" | "as" | "style"
> & {
style?: JSX.CSSProperties;
children?: Children;
width: number;
height: number;
};
export function SizedGrid(props: Props) {
const { width, height, children, style, ...divProps } = props;
const { width, height, children, ...divProps } = props;
return (
<Grid
{...divProps}
style={{
...style,
"--width": `${width}px`,
"--height": `${height}px`,
"--aspect-ratio": width / height,
}}>
<Grid {...divProps} width={width} height={height}>
{children}
</Grid>
);

View File

@@ -0,0 +1,47 @@
import { Attachment } from "revolt-api/types/Autumn";
import styles from "./Attachment.module.scss";
import classNames from "classnames";
import { useContext, useState } from "preact/hooks";
import { useIntermediate } from "../../../../context/intermediate/Intermediate";
import { AppContext } from "../../../../context/revoltjs/RevoltClient";
enum ImageLoadingState {
Loading,
Loaded,
Error
}
type Props = JSX.HTMLAttributes<HTMLImageElement> & {
attachment: Attachment;
}
export default function ImageFile({ attachment, ...props }: Props) {
const [loading, setLoading] = useState(ImageLoadingState.Loading);
const client = useContext(AppContext);
const { openScreen } = useIntermediate();
const url = client.generateFileURL(attachment)!;
return <img
{...props}
src={url}
alt={attachment.filename}
loading="lazy"
className={classNames(styles.image, {
[styles.loading]: loading !== ImageLoadingState.Loaded
})}
onClick={() =>
openScreen({ id: "image_viewer", attachment })
}
onMouseDown={(ev) =>
ev.button === 1 && window.open(url, "_blank")
}
onLoad={() =>
setLoading(ImageLoadingState.Loaded)
}
onError={() =>
setLoading(ImageLoadingState.Error)
}
/>
}

View File

@@ -1,24 +1,24 @@
import { Reply } from "@styled-icons/boxicons-regular";
import { File } from "@styled-icons/boxicons-solid";
import { observer } from "mobx-react-lite";
import { useHistory } from "react-router-dom";
import { SYSTEM_USER_ID } from "revolt.js";
import { Users } from "revolt.js/dist/api/objects";
import { RelationshipStatus } from "revolt-api/types/Users";
import { Channel } from "revolt.js/dist/maps/Channels";
import { Message } from "revolt.js/dist/maps/Messages";
import styled, { css } from "styled-components";
import { Text } from "preact-i18n";
import { useLayoutEffect, useState } from "preact/hooks";
import { useRenderState } from "../../../../lib/renderer/Singleton";
import { useForceUpdate, useUser } from "../../../../context/revoltjs/hooks";
import { mapMessage, MessageObject } from "../../../../context/revoltjs/util";
import { getRenderer } from "../../../../lib/renderer/Singleton";
import Markdown from "../../../markdown/Markdown";
import UserShort from "../../user/UserShort";
import { SystemMessage } from "../SystemMessage";
interface Props {
channel: string;
parent_mentions: string[];
channel: Channel;
index: number;
id: string;
}
@@ -29,15 +29,30 @@ export const ReplyBase = styled.div<{
preview?: boolean;
}>`
gap: 4px;
min-width: 0;
display: flex;
margin-inline-start: 30px;
margin-inline-end: 12px;
margin-bottom: 4px;
font-size: 0.8em;
user-select: none;
align-items: center;
color: var(--secondary-foreground);
/* nizune's Discord replies,
does not scale properly with messages,
reverted temporarily
&::before {
content: "";
height: 10px;
width: 28px;
margin-inline-end: 2px;
align-self: flex-end;
display: flex;
border-top: 2.2px solid var(--tertiary-foreground);
border-inline-start: 2.2px solid var(--tertiary-foreground);
border-start-start-radius: 6px;
}*/
* {
overflow: hidden;
white-space: nowrap;
@@ -45,11 +60,13 @@ export const ReplyBase = styled.div<{
}
.user {
gap: 6px;
display: flex;
gap: 4px;
flex-shrink: 0;
font-weight: 600;
overflow: visible;
align-items: center;
padding: 2px 0;
span {
cursor: pointer;
@@ -67,11 +84,16 @@ export const ReplyBase = styled.div<{
}
.content {
max-height: 32px;
gap: 4px;
display: flex;
padding: 2px 0;
cursor: pointer;
overflow: hidden;
align-items: center;
flex-direction: row;
transition: filter 1s ease-in-out;
transition: transform ease-in-out 0.1s;
filter: brightness(1);
@@ -88,9 +110,9 @@ export const ReplyBase = styled.div<{
pointer-events: none;
}
> span {
/*> span > p {
display: flex;
}
}*/
}
> svg:first-child {
@@ -118,87 +140,99 @@ export const ReplyBase = styled.div<{
`}
`;
export function MessageReply({ index, channel, id }: Props) {
const ctx = useForceUpdate();
const view = useRenderState(channel);
if (view?.type !== "RENDER") return null;
export const MessageReply = observer(
({ index, channel, id, parent_mentions }: Props) => {
const view = getRenderer(channel);
if (view.state !== "RENDER") return null;
const [message, setMessage] = useState<MessageObject | undefined>(
undefined,
);
useLayoutEffect(() => {
// ! FIXME: We should do this through the message renderer, so it can fetch it from cache if applicable.
const m = view.messages.find((x) => x._id === id);
const [message, setMessage] = useState<Message | undefined>(undefined);
if (m) {
setMessage(m);
} else {
ctx.client.channels
.fetchMessage(channel, id)
.then((m) => setMessage(mapMessage(m)));
useLayoutEffect(() => {
const message = channel.client.messages.get(id);
if (message) {
setMessage(message);
} else {
channel.fetchMessage(id).then(setMessage);
}
}, [id, channel, view.messages]);
if (!message) {
return (
<ReplyBase head={index === 0} fail>
<Reply size={16} />
<span>
<Text id="app.main.channel.misc.failed_load" />
</span>
</ReplyBase>
);
}
}, [view.messages]);
if (!message) {
const history = useHistory();
return (
<ReplyBase head={index === 0} fail>
<ReplyBase head={index === 0}>
<Reply size={16} />
<span>
<Text id="app.main.channel.misc.failed_load" />
</span>
{message.author?.relationship === RelationshipStatus.Blocked ? (
<Text id="app.main.channel.misc.blocked_user" />
) : (
<>
{message.author_id === "00000000000000000000000000" ? (
<SystemMessage message={message} hideInfo />
) : (
<>
<div className="user">
<UserShort
size={16}
showServerIdentity
user={message.author}
masquerade={message.masquerade!}
prefixAt={parent_mentions.includes(
message.author_id,
)}
/>
</div>
<div
className="content"
onClick={() => {
const channel = message.channel!;
if (
channel.channel_type ===
"TextChannel"
) {
history.push(
`/server/${channel.server_id}/channel/${channel._id}/${message._id}`,
);
} else {
history.push(
`/channel/${channel._id}/${message._id}`,
);
}
}}>
{message.attachments && (
<>
<File size={16} />
<em>
{message.attachments.length >
1 ? (
<Text id="app.main.channel.misc.sent_multiple_files" />
) : (
<Text id="app.main.channel.misc.sent_file" />
)}
</em>
</>
)}
<Markdown
disallowBigEmoji
content={(
message.content as string
).replace(/\n/g, " ")}
/>
</div>
</>
)}
</>
)}
</ReplyBase>
);
}
const user = useUser(message.author, ctx);
const history = useHistory();
return (
<ReplyBase head={index === 0}>
<Reply size={16} />
{user?.relationship === Users.Relationship.Blocked ? (
<>
<Text id="app.main.channel.misc.blocked_user" />
</>
) : (
<>
{message.author === SYSTEM_USER_ID ? (
<SystemMessage message={message} hideInfo />
) : (
<>
<div className="user">
<UserShort user={user} size={16} />
</div>
<div
className="content"
onClick={() => {
const obj =
ctx.client.channels.get(channel);
if (obj?.channel_type === "TextChannel") {
history.push(
`/server/${obj.server}/channel/${obj._id}/${message._id}`,
);
} else {
history.push(
`/channel/${channel}/${message._id}`,
);
}
}}>
{message.attachments &&
message.attachments.length > 0 && (
<File size={16} />
)}
<Markdown
disallowBigEmoji
content={(
message.content as string
).replace(/\n/g, " ")}
/>
</div>
</>
)}
</>
)}
</ReplyBase>
);
}
},
);

Some files were not shown because too many files have changed in this diff Show More