├── ErrorBoundary.jsx
├── LICENSE
├── Preview.jsx
├── README.md
├── Settings.jsx
├── index.js
├── manifest.json
└── style.css
/ErrorBoundary.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020-2021 Cynthia K. Rey, All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are met:
6 | *
7 | * 1. Redistributions of source code must retain the above copyright notice, this
8 | * list of conditions and the following disclaimer.
9 | * 2. Redistributions in binary form must reproduce the above copyright notice,
10 | * this list of conditions and the following disclaimer in the
11 | * documentation and/or other materials provided with the distribution.
12 | * 3. Neither the name of the copyright holder nor the names of its contributors
13 | * may be used to endorse or promote products derived from this software without
14 | * specific prior written permission.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | const { resolve } = require('path')
29 | const { React, getModule } = require('powercord/webpack')
30 | const { Card } = require('powercord/components')
31 | const { DISCORD_INVITE, SpecialChannels: { SUPPORT_PLUGINS }, SETTINGS_FOLDER } = require('powercord/constants')
32 | const { gotoOrJoinServer } = require('powercord/util')
33 |
34 | const REPO = 'cyyynthia/better-replies'
35 |
36 | class ErrorBoundary extends React.PureComponent {
37 | constructor (props) {
38 | super(props)
39 |
40 | this.state = { crashed: false }
41 | }
42 |
43 | componentDidCatch (e) {
44 | const basePath = resolve(SETTINGS_FOLDER, '..')
45 |
46 | this.setState({
47 | crashed: true,
48 | error: (e.stack || '')
49 | .split('\n')
50 | .filter(l => !l.includes('discordapp.com/assets/') && !l.includes('discord.com/assets/'))
51 | .join('\n')
52 | .split(basePath)
53 | .join('')
54 | })
55 | }
56 |
57 | render () {
58 | if (this.state.crashed) {
59 | return (
60 |
61 |
62 | An error occurred while rendering the preview. Please let Cynthia know by sending her a message with the
63 | error message on the Powercord server, or by opening an issue
64 | on the GitHub repository.
65 |
66 | {this.state.error}
67 |
68 | )
69 | }
70 |
71 | return this.props.children
72 | }
73 |
74 | joinPorkord () {
75 | getModule([ 'popLayer' ], false).popLayer()
76 | gotoOrJoinServer(DISCORD_INVITE, SUPPORT_PLUGINS)
77 | }
78 | }
79 |
80 | module.exports = ErrorBoundary
81 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2020-2021 Cynthia K. Rey, All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are met:
5 |
6 | 1. Redistributions of source code must retain the above copyright notice, this
7 | list of conditions and the following disclaimer.
8 | 2. Redistributions in binary form must reproduce the above copyright notice,
9 | this list of conditions and the following disclaimer in the
10 | documentation and/or other materials provided with the distribution.
11 | 3. Neither the name of the copyright holder nor the names of its contributors
12 | may be used to endorse or promote products derived from this software without
13 | specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/Preview.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020-2021 Cynthia K. Rey, All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are met:
6 | *
7 | * 1. Redistributions of source code must retain the above copyright notice, this
8 | * list of conditions and the following disclaimer.
9 | * 2. Redistributions in binary form must reproduce the above copyright notice,
10 | * this list of conditions and the following disclaimer in the
11 | * documentation and/or other materials provided with the distribution.
12 | * 3. Neither the name of the copyright holder nor the names of its contributors
13 | * may be used to endorse or promote products derived from this software without
14 | * specific prior written permission.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | const { React, getModule } = require('powercord/webpack');
29 |
30 | const ChannelMessage = getModule([ 'getElementFromMessageId' ], false).default;
31 | const Message = getModule(m => m.prototype && m.prototype.getReaction && m.prototype.isSystemDM, false);
32 | const DiscordSettings = getModule([ 'MessageDisplayCompact' ], false);
33 |
34 | const CHANNEL = {
35 | isPrivate: () => false,
36 | isSystemDM: () => false,
37 | getGuildId: () => 'uwu',
38 | isArchivedThread: () => false,
39 | isThread: () => false,
40 | isForumPost: () => false,
41 | };
42 |
43 | const MESSAGE_REF = new Message({
44 | id: 'owo',
45 | author: {
46 | id: 'a',
47 | username: 'Ben',
48 | toString: () => 'Ben',
49 | isSystemUser: () => false,
50 | isVerifiedBot: () => false,
51 | isNonUserBot: () => false,
52 | getAvatarURL: () => 'https://powercord.dev/api/v2/avatar/465668689920917534.png'
53 | },
54 | content: 'Cynthia be droppin another hot plugin soon™️',
55 | });
56 |
57 | const MESSAGE = new Message({
58 | id: 'uwu',
59 | type: 19,
60 | author: {
61 | id: 'b',
62 | username: 'Cynthia 🌹',
63 | toString: () => 'Cynthia 🌹',
64 | isSystemUser: () => false,
65 | isVerifiedBot: () => false,
66 | isNonUserBot: () => false,
67 | getAvatarURL: () => 'https://powercord.dev/api/v2/avatar/94762492923748352.png'
68 | },
69 | content: 'Heck yeah 😎',
70 | messageReference: { __betterRepliesFakeMessage: MESSAGE_REF },
71 | });
72 |
73 | function Settings ({ appearance }) {
74 | const compact = DiscordSettings.MessageDisplayCompact.useSetting()
75 |
76 | return (
77 |
78 |
85 |
86 | );
87 | }
88 |
89 | module.exports = React.memo(Settings);
90 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Better Replies
2 |
3 | Enhances replies and gives them the customization they need. Change their appearance and behavior easily, to your
4 | likings.
5 |
--------------------------------------------------------------------------------
/Settings.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020-2021 Cynthia K. Rey, All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are met:
6 | *
7 | * 1. Redistributions of source code must retain the above copyright notice, this
8 | * list of conditions and the following disclaimer.
9 | * 2. Redistributions in binary form must reproduce the above copyright notice,
10 | * this list of conditions and the following disclaimer in the
11 | * documentation and/or other materials provided with the distribution.
12 | * 3. Neither the name of the copyright holder nor the names of its contributors
13 | * may be used to endorse or promote products derived from this software without
14 | * specific prior written permission.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | const { React } = require('powercord/webpack');
29 | const { FormTitle } = require('powercord/components');
30 | const { RadioGroup, SwitchItem } = require('powercord/components/settings');
31 |
32 | const ErrorBoundary = require('./ErrorBoundary.jsx')
33 | const Preview = require('./Preview.jsx')
34 |
35 | function Settings ({ getSetting, updateSetting, toggleSetting }) {
36 | return (
37 | <>
38 |
39 |
40 |
41 |
42 | Settings
43 |
44 | updateSetting('appearance', e.value)}
46 | value={getSetting('appearance', 'default')}
47 | options={[
48 | {
49 | name: 'Default',
50 | desc: 'Shows above the entire message.',
51 | value: 'default'
52 | },
53 | {
54 | name: 'Quote',
55 | desc: 'Will show as a quote, just above the message contents.',
56 | value: 'quote'
57 | },
58 | {
59 | name: 'Hidden',
60 | desc: 'This will completely disable inline replies from showing up.',
61 | value: 'hidden'
62 | }
63 | ]}
64 | >
65 | Appearance
66 |
67 | updateSetting('mention', e.value)}
70 | value={getSetting('mention', 'always')}
71 | options={[
72 | {
73 | name: 'Always mention',
74 | desc: 'Default behavior. When replying, the mention will always be enabled.',
75 | value: 'always'
76 | },
77 | {
78 | name: 'Remember',
79 | desc: 'Will remember your last setting and re-apply it. If you disabled it it\'ll remain disabled and vice-versa.',
80 | value: 'remember'
81 | },
82 | {
83 | name: 'Never mention',
84 | desc: 'When replying, the mention will never be enabled.',
85 | value: 'never'
86 | }
87 | ]}
88 | >
89 | Outgoing replies settings
90 |
91 | updateSetting('ping', e.value)}
94 | value={getSetting('ping', 'default')}
95 | options={[
96 | {
97 | name: 'Default',
98 | desc: 'Honors the set behavior by the sender.',
99 | value: 'default'
100 | },
101 | {
102 | name: 'Never ping',
103 | desc: 'Suppress ping from replies sent with ping enabled. Note: this has no effect on mobile notifications.',
104 | value: 'never'
105 | },
106 | {
107 | name: 'Always ping',
108 | desc: 'Ping even if the sender disabled the ping. Note: this has no effect on mobile notifications.',
109 | value: 'always'
110 | }
111 | ]}
112 | >
113 | Incoming replies settings
114 |
115 | toggleSetting('quick-toggle')}
119 | note2={'Whether the mention should be toggled when pressing backspace while you\'re at the beginning of the message. Currently a bit buggy :('}
120 | note={'This setting has been disabled due to a bug. Will be hopefully back before 2030.'}
121 | >
122 | Quick toggle
123 |
124 | >
125 | );
126 | }
127 |
128 | module.exports = React.memo(Settings);
129 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020-2021 Cynthia K. Rey, All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are met:
6 | *
7 | * 1. Redistributions of source code must retain the above copyright notice, this
8 | * list of conditions and the following disclaimer.
9 | * 2. Redistributions in binary form must reproduce the above copyright notice,
10 | * this list of conditions and the following disclaimer in the
11 | * documentation and/or other materials provided with the distribution.
12 | * 3. Neither the name of the copyright holder nor the names of its contributors
13 | * may be used to endorse or promote products derived from this software without
14 | * specific prior written permission.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | const { React, getModule } = require('powercord/webpack');
29 | const { Tooltip } = require('powercord/components');
30 | const { findInReactTree } = require('powercord/util');
31 | const { inject, uninject } = require('powercord/injector');
32 | const { Plugin } = require('powercord/entities');
33 |
34 | const Settings = require('./Settings');
35 |
36 | module.exports = class BetterReplies extends Plugin {
37 | async startPlugin () {
38 | this.loadStylesheet('style.css');
39 | powercord.api.settings.registerSettings(this.entityID, {
40 | category: this.entityID,
41 | label: 'Better Replies',
42 | render: Settings
43 | });
44 |
45 | this.injectOutgoingReplies()
46 | this.injectIncomingReplies()
47 | this.injectFakeReference()
48 | }
49 |
50 | async injectOutgoingReplies () {
51 | const userStore = await getModule([ 'getCurrentUser', 'getUser' ]);
52 | const replierMdl = await getModule([ 'createPendingReply' ]);
53 | const Message = await getModule(m => (m.__powercordOriginal_default || m.default)?.toString().includes('childrenRepliedMessage'));
54 | const ChannelReply = await getModule(m => m.default?.displayName === 'ChannelReply');
55 | const ChannelTextAreaContainer = await getModule((m) => m.type?.render?.displayName === 'ChannelTextAreaContainer');
56 |
57 | inject('brep-reply-mention-setting', replierMdl, 'createPendingReply', (args) => {
58 | const mode = this.settings.get('mention', 'always');
59 | if (mode === 'never') {
60 | args[0].shouldMention = false;
61 | }
62 |
63 | if (mode === 'remember') {
64 | const u = userStore.getCurrentUser();
65 | args[0].shouldMention = args[0].message.author.id !== u.id && this.settings.get('--mention-cache', true);
66 | }
67 |
68 | return args;
69 | }, true);
70 |
71 | inject('brep-reply-mention-toggle', ChannelReply, 'default', (_, res) => {
72 | const tooltip = findInReactTree(res, n => n.disableTooltipPointerEvents);
73 | const renderer = tooltip.children;
74 | tooltip.children = (e) => {
75 | const res = renderer(e);
76 | const checked = res.props['aria-checked'];
77 | const handler = res.props.onClick;
78 | res.props.onClick = (e) => {
79 | this.settings.set('--mention-cache', !checked);
80 | handler(e);
81 | };
82 | return res;
83 | };
84 | return res;
85 | });
86 |
87 | inject('brep-reply-appearance', Message, 'default', (_, res) => {
88 | const appearance = this.settings.get('appearance', 'default');
89 | if (appearance === 'quote') {
90 | res.props.children.props.children[2].props.children.splice(2, 0, res.props.children.props.children[0]);
91 | }
92 | if (appearance !== 'default') {
93 | res.props.children.props.children[0] = null;
94 | }
95 |
96 | return res;
97 | });
98 |
99 | /*
100 | inject('brep-reply-quick-toggle', ChannelTextAreaContainer.type, 'render', (args, res) => {
101 | const ta = findInReactTree(res, n => n.richValue && n.onKeyDown);
102 | if (ta.onKeyDown !== prevFn) {
103 | prevFn = ta.onKeyDown;
104 | injectedFn = ((prev, e) => {
105 | // I cba to do something decent, DOM access is enough
106 | const quickToggle = this.settings.get('quick-toggle', false);
107 | const toggler = document.querySelector('.channelTextArea-rNsIhG .mentionButton-3710-W');
108 | const reactInstance = getReactInstance(document.querySelector('.channelTextArea-rNsIhG'));
109 | const textarea = findInReactTree(reactInstance.memoizedProps, n => n.richValue && n.onKeyDown);
110 | const { selection } = textarea.richValue;
111 |
112 | // todo: fix this shit
113 | if (quickToggle && toggler && e.key === 'Backspace' && selection.start.offset === 0 && selection.end.offset === 0) {
114 | toggler.click();
115 | return;
116 | }
117 | prev(e);
118 | }).bind(null, prevFn);
119 | }
120 |
121 | ta.onKeyDown = injectedFn;
122 | return res;
123 | });
124 | */
125 |
126 | ChannelReply.default.displayName = 'ChannelReply';
127 | ChannelTextAreaContainer.type.render.displayName = 'ChannelTextAreaContainer';
128 | }
129 |
130 | async injectIncomingReplies () {
131 | const userStore = await getModule([ 'getCurrentUser', 'getUser' ]);
132 | const messageHandler = await getModule([ 'createMessageRecord' ])
133 | const RepliedMessage = await getModule((m) => m.default?.displayName === 'RepliedMessage')
134 |
135 | inject('brep-notif-receive', messageHandler, 'createMessageRecord', (args) => {
136 | const msg = args[0]
137 | const user = userStore.getCurrentUser()
138 | const mode = this.settings.get('ping', 'default')
139 |
140 | if (mode === 'default' || msg.state === 'SENDING' || !msg.referenced_message) {
141 | return args
142 | }
143 |
144 | const isMentioned = Boolean(msg.mentions.find((u) => u.id === user.id))
145 | if (mode === 'never' && !msg.mention_everyone && isMentioned && !msg.content.includes(user.id)) {
146 | msg.message_reference.__brepSuppressed = true
147 | msg.mentions = msg.mentions.filter((u) => u.id !== user.id)
148 | }
149 |
150 | if (mode === 'always' && !isMentioned && msg.referenced_message.author.id === user.id && msg.author.id !== user.id) {
151 | msg.message_reference.__brepEnforced = true
152 | msg.mentions.push(user)
153 | }
154 |
155 | return args
156 | }, true)
157 |
158 | inject('brep-notif-visual', RepliedMessage, 'default', ([ { baseMessage: { messageReference } } ], res) => {
159 | if (messageReference.__brepEnforced || messageReference.__brepSuppressed) {
160 | const idx = res.props.children.findIndex((n) =>'withMentionPrefix' in n.props)
161 | const username = res.props.children[idx]
162 | username.props.withMentionPrefix = false
163 |
164 | if (messageReference.__brepSuppressed) {
165 | res.props.children[idx] = [
166 | React.createElement(Tooltip, { text: 'Ping suppressed' },
167 | React.createElement('span', { style: { color: 'var(--text-muted)' } }, '@')),
168 | username
169 | ]
170 | }
171 | }
172 | return res
173 | })
174 |
175 | RepliedMessage.default.displayName = 'RepliedMessage'
176 | }
177 |
178 | async injectFakeReference () {
179 | const referenceStore = await getModule([ 'getMessageByReference' ]);
180 |
181 | inject('brep-fake-ref', referenceStore, 'getMessageByReference', (args, res) => {
182 | if (args[0]?.__betterRepliesFakeMessage) {
183 | return {
184 | message: args[0].__betterRepliesFakeMessage,
185 | state: 0
186 | };
187 | }
188 |
189 | return res;
190 | });
191 | }
192 |
193 | pluginWillUnload () {
194 | powercord.api.settings.unregisterSettings(this.entityID);
195 | uninject('brep-reply-mention-setting');
196 | uninject('brep-reply-mention-toggle');
197 | uninject('brep-reply-appearance');
198 | uninject('brep-reply-quick-toggle');
199 |
200 | uninject('brep-notif-receive')
201 | uninject('brep-notif-visual')
202 |
203 | uninject('brep-fake-ref');
204 | }
205 | };
206 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Better Replies",
3 | "version": "1.2.0",
4 | "description": "Enhances replies and gives them the customization they need. Change their appearance and behavior easily, to your likings.",
5 | "author": "Cynthia",
6 | "license": "BSD-3-Clause"
7 | }
8 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020-2021 Cynthia K. Rey, All rights reserved.
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions are met:
6 | *
7 | * 1. Redistributions of source code must retain the above copyright notice, this
8 | * list of conditions and the following disclaimer.
9 | * 2. Redistributions in binary form must reproduce the above copyright notice,
10 | * this list of conditions and the following disclaimer in the
11 | * documentation and/or other materials provided with the distribution.
12 | * 3. Neither the name of the copyright holder nor the names of its contributors
13 | * may be used to endorse or promote products derived from this software without
14 | * specific prior written permission.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | /* If it's tucked there, it's meant to be shown as a quote */
29 | .contents-2MsGLg .repliedMessage-3Z6XBG {
30 | padding: 4px 14px;
31 | margin: 4px 0;
32 | }
33 |
34 | .contents-2MsGLg .repliedMessage-3Z6XBG::before {
35 | left: 0;
36 | top: 0;
37 | bottom: 0;
38 | margin: 0;
39 | right: auto;
40 | }
41 |
42 | .compact-2Nkcau .contents-2MsGLg .repliedMessage-3Z6XBG {
43 | margin: 0;
44 | padding: 2px 8px;
45 | }
46 |
47 | .compact-2Nkcau .contents-2MsGLg .repliedMessage-3Z6XBG .username-h_Y3Us,
48 | .compact-2Nkcau .contents-2MsGLg .repliedMessage-3Z6XBG .repliedTextPreview-1bvxun {
49 | text-indent: 0;
50 | }
51 |
52 | .better-replies-hidden, .better-replies-hidden + span {
53 | display: none;
54 | }
55 |
56 | .better-replies-preview-container {
57 | margin-bottom: 20px;
58 | pointer-events: none;
59 | }
60 |
61 | .better-replies-preview-container * {
62 | pointer-events: none !important;
63 | }
64 |
65 | .better-replies-error {
66 | padding: 20px;
67 | margin-bottom: 20px;
68 | color: var(--text-normal);
69 | border-color: #f04747;
70 | background-color: #f0474730;
71 | }
72 |
73 | .better-replies-error p {
74 | margin: 0;
75 | margin-bottom: 8px;
76 | }
77 |
78 | .better-replies-error code {
79 | user-select: text;
80 | }
81 |
--------------------------------------------------------------------------------