Compare commits
3 Commits
747107169b
...
411e3d38e0
Author | SHA1 | Date | |
---|---|---|---|
411e3d38e0 | |||
9d12853be0 | |||
89cbc770de |
@ -9,9 +9,10 @@
|
|||||||
<h2 class="help-version-title">
|
<h2 class="help-version-title">
|
||||||
<span>About Hard Lounge</span>
|
<span>About Hard Lounge</span>
|
||||||
<small>
|
<small>
|
||||||
v{{ store.state.serverConfiguration?.version }} (<router-link
|
v{{
|
||||||
id="view-changelog"
|
store.state.serverConfiguration?.version
|
||||||
to="/changelog"
|
}}
|
||||||
|
(<router-link id="view-changelog" to="/changelog"
|
||||||
>release notes</router-link
|
>release notes</router-link
|
||||||
>)
|
>)
|
||||||
</small>
|
</small>
|
||||||
@ -53,8 +54,8 @@
|
|||||||
<div class="help-item">
|
<div class="help-item">
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
IRC.SUPERNETS.ORG #SUPERBOWL FUCK YOUR NETWORK COLD HARD CHATS THIS IS NOT
|
IRC.SUPERNETS.ORG #SUPERBOWL FUCK YOUR NETWORK COLD HARD
|
||||||
YOUR DADS FOOTBALL CHANNEL
|
CHATS THIS IS NOT YOUR DADS FOOTBALL CHANNEL
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -93,7 +94,9 @@
|
|||||||
|
|
||||||
<div class="help-item">
|
<div class="help-item">
|
||||||
<div class="subject">
|
<div class="subject">
|
||||||
<span v-if="!isApple"><kbd>Alt</kbd> <kbd>Shift</kbd> <kbd>↓</kbd></span>
|
<span v-if="!isApple"
|
||||||
|
><kbd>Alt</kbd> <kbd>Shift</kbd> <kbd>↓</kbd></span
|
||||||
|
>
|
||||||
<span v-else><kbd>⌥</kbd> <kbd>⇧</kbd> <kbd>↓</kbd></span>
|
<span v-else><kbd>⌥</kbd> <kbd>⇧</kbd> <kbd>↓</kbd></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
@ -103,7 +106,9 @@
|
|||||||
|
|
||||||
<div class="help-item">
|
<div class="help-item">
|
||||||
<div class="subject">
|
<div class="subject">
|
||||||
<span v-if="!isApple"><kbd>Alt</kbd> <kbd>Shift</kbd> <kbd>↑</kbd></span>
|
<span v-if="!isApple"
|
||||||
|
><kbd>Alt</kbd> <kbd>Shift</kbd> <kbd>↑</kbd></span
|
||||||
|
>
|
||||||
<span v-else><kbd>⌥</kbd> <kbd>⇧</kbd> <kbd>↑</kbd></span>
|
<span v-else><kbd>⌥</kbd> <kbd>⇧</kbd> <kbd>↑</kbd></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
@ -113,7 +118,9 @@
|
|||||||
|
|
||||||
<div class="help-item">
|
<div class="help-item">
|
||||||
<div class="subject">
|
<div class="subject">
|
||||||
<span v-if="!isApple"><kbd>Alt</kbd> <kbd>Shift</kbd> <kbd>←</kbd></span>
|
<span v-if="!isApple"
|
||||||
|
><kbd>Alt</kbd> <kbd>Shift</kbd> <kbd>←</kbd></span
|
||||||
|
>
|
||||||
<span v-else><kbd>⌥</kbd> <kbd>⇧</kbd> <kbd>←</kbd></span>
|
<span v-else><kbd>⌥</kbd> <kbd>⇧</kbd> <kbd>←</kbd></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
@ -123,7 +130,9 @@
|
|||||||
|
|
||||||
<div class="help-item">
|
<div class="help-item">
|
||||||
<div class="subject">
|
<div class="subject">
|
||||||
<span v-if="!isApple"><kbd>Alt</kbd> <kbd>Shift</kbd> <kbd>→</kbd></span>
|
<span v-if="!isApple"
|
||||||
|
><kbd>Alt</kbd> <kbd>Shift</kbd> <kbd>→</kbd></span
|
||||||
|
>
|
||||||
<span v-else><kbd>⌥</kbd> <kbd>⇧</kbd> <kbd>→</kbd></span>
|
<span v-else><kbd>⌥</kbd> <kbd>⇧</kbd> <kbd>→</kbd></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
@ -217,8 +226,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Close current contextual window (context menu, image viewer, topic edit,
|
Close current contextual window (context menu, image
|
||||||
etc) and remove focus from input.
|
viewer, topic edit, etc) and remove focus from input.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -232,15 +241,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Mark any text typed after this shortcut to be colored. After hitting this
|
Mark any text typed after this shortcut to be colored.
|
||||||
shortcut, enter an integer in the range
|
After hitting this shortcut, enter an integer in the
|
||||||
<code>0—15</code> to select the desired color, or use the autocompletion
|
range
|
||||||
menu to choose a color name (see below).
|
<code>0—15</code> to select the desired color, or use
|
||||||
|
the autocompletion menu to choose a color name (see
|
||||||
|
below).
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Background color can be specified by putting a comma and another integer in
|
Background color can be specified by putting a comma and
|
||||||
the range <code>0—15</code> after the foreground color number
|
another integer in the range <code>0—15</code> after the
|
||||||
(autocompletion works too).
|
foreground color number (autocompletion works too).
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
A color reference can be found
|
A color reference can be found
|
||||||
@ -326,8 +337,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Mark all text typed after this shortcut to be reset to its original
|
Mark all text typed after this shortcut to be reset to
|
||||||
formatting.
|
its original formatting.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -335,10 +346,11 @@
|
|||||||
<h2>Autocompletion</h2>
|
<h2>Autocompletion</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
To auto-complete nicknames, channels, commands, and emoji, type one of the
|
To auto-complete nicknames, channels and commands, type one of
|
||||||
characters below to open a suggestion list. Use the <kbd>↑</kbd> and
|
the characters below to open a suggestion list. Use the
|
||||||
<kbd>↓</kbd> keys to highlight an item, and insert it by pressing <kbd>Tab</kbd> or
|
<kbd>↑</kbd> and <kbd>↓</kbd> keys to highlight an item, and
|
||||||
<kbd>Enter</kbd> (or by clicking the desired item).
|
insert it by pressing <kbd>Tab</kbd> or <kbd>Enter</kbd> (or by
|
||||||
|
clicking the desired item).
|
||||||
</p>
|
</p>
|
||||||
<p>Autocompletion can be disabled in settings.</p>
|
<p>Autocompletion can be disabled in settings.</p>
|
||||||
|
|
||||||
@ -369,18 +381,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="help-item">
|
|
||||||
<div class="subject">
|
|
||||||
<code>:</code>
|
|
||||||
</div>
|
|
||||||
<div class="description">
|
|
||||||
<p>
|
|
||||||
Emoji (note: requires two search characters, to avoid conflicting with
|
|
||||||
common emoticons like <code>:)</code>)
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>Commands</h2>
|
<h2>Commands</h2>
|
||||||
|
|
||||||
<div class="help-item">
|
<div class="help-item">
|
||||||
@ -397,7 +397,9 @@
|
|||||||
<code>/back</code>
|
<code>/back</code>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>Remove your away status (set with <code>/away</code>).</p>
|
<p>
|
||||||
|
Remove your away status (set with <code>/away</code>).
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -407,8 +409,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Ban (<code>+b</code>) a user from the current channel. This can be a
|
Ban (<code>+b</code>) a user from the current channel.
|
||||||
nickname or a hostmask.
|
This can be a nickname or a hostmask.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -428,7 +430,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Collapse all previews in the current channel (opposite of
|
Collapse all previews in the current channel (opposite
|
||||||
|
of
|
||||||
<code>/expand</code>)
|
<code>/expand</code>)
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -440,8 +443,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Connect to a new IRC network. If <code>port</code> starts with a
|
Connect to a new IRC network. If
|
||||||
<code>+</code> sign, the connection will be made secure using TLS.
|
<code>port</code> starts with a <code>+</code> sign, the
|
||||||
|
connection will be made secure using TLS.
|
||||||
</p>
|
</p>
|
||||||
<p>Alias: <code>/server</code></p>
|
<p>Alias: <code>/server</code></p>
|
||||||
</div>
|
</div>
|
||||||
@ -453,7 +457,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Send a <abbr title="Client-to-client protocol">CTCP</abbr>
|
Send a
|
||||||
|
<abbr title="Client-to-client protocol">CTCP</abbr>
|
||||||
request. Read more about this on
|
request. Read more about this on
|
||||||
<a
|
<a
|
||||||
href="https://en.wikipedia.org/wiki/Client-to-client_protocol"
|
href="https://en.wikipedia.org/wiki/Client-to-client_protocol"
|
||||||
@ -471,8 +476,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Remove op (<code>-o</code>) from one or several users in the current
|
Remove op (<code>-o</code>) from one or several users in
|
||||||
channel.
|
the current channel.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -483,8 +488,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Remove voice (<code>-v</code>) from one or several users in the current
|
Remove voice (<code>-v</code>) from one or several users
|
||||||
channel.
|
in the current channel.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -494,7 +499,10 @@
|
|||||||
<code>/disconnect [message]</code>
|
<code>/disconnect [message]</code>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>Disconnect from the current network with an optionally-provided message.</p>
|
<p>
|
||||||
|
Disconnect from the current network with an
|
||||||
|
optionally-provided message.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -517,8 +525,8 @@
|
|||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Invite a user to the specified channel. If
|
Invite a user to the specified channel. If
|
||||||
<code>channel</code> is omitted, user will be invited to the current
|
<code>channel</code> is omitted, user will be invited to
|
||||||
channel.
|
the current channel.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -529,8 +537,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Block any messages from the specified user on the current network. This can
|
Block any messages from the specified user on the
|
||||||
be a nickname or a hostmask.
|
current network. This can be a nickname or a hostmask.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -540,7 +548,9 @@
|
|||||||
<code>/ignorelist</code>
|
<code>/ignorelist</code>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>Load the list of ignored users for the current network.</p>
|
<p>
|
||||||
|
Load the list of ignored users for the current network.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -550,8 +560,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Join a channel. Password is only needed in protected channels and can
|
Join a channel. Password is only needed in protected
|
||||||
usually be omitted.
|
channels and can usually be omitted.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -571,8 +581,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Kick and ban (<code>+b</code>) a user from the current channel. Unlike
|
Kick and ban (<code>+b</code>) a user from the current
|
||||||
<code>/ban</code>, only nicknames (and not host masks) can be used.
|
channel. Unlike
|
||||||
|
<code>/ban</code>, only nicknames (and not host masks)
|
||||||
|
can be used.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -582,7 +594,9 @@
|
|||||||
<code>/list</code>
|
<code>/list</code>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>Retrieve a list of available channels on this network.</p>
|
<p>
|
||||||
|
Retrieve a list of available channels on this network.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -592,8 +606,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Send an action message to the current channel. Hard Lounge will display it
|
Send an action message to the current channel. Hard
|
||||||
inline, as if the message was posted in the third person.
|
Lounge will display it inline, as if the message was
|
||||||
|
posted in the third person.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -604,9 +619,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Set the given flags to the current channel if the active window is a
|
Set the given flags to the current channel if the active
|
||||||
channel, another user if the active window is a private message window, or
|
window is a channel, another user if the active window
|
||||||
yourself if the current window is a server window.
|
is a private message window, or yourself if the current
|
||||||
|
window is a server window.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -626,10 +642,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Prevent messages from generating any feedback for a channel. This turns off
|
Prevent messages from generating any feedback for a
|
||||||
the highlight indicator, hides mentions and inhibits push notifications.
|
channel. This turns off the highlight indicator, hides
|
||||||
Muting a network lobby mutes the entire network. Not specifying any channel
|
mentions and inhibits push notifications. Muting a
|
||||||
target mutes the current channel. Revert with <code>/unmute</code>.
|
network lobby mutes the entire network. Not specifying
|
||||||
|
any channel target mutes the current channel. Revert
|
||||||
|
with <code>/unmute</code>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -657,7 +675,10 @@
|
|||||||
<code>/op nick [...nick]</code>
|
<code>/op nick [...nick]</code>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>Give op (<code>+o</code>) to one or several users in the current channel.</p>
|
<p>
|
||||||
|
Give op (<code>+o</code>) to one or several users in the
|
||||||
|
current channel.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -667,8 +688,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Close the specified channel or private message window, or the current
|
Close the specified channel or private message window,
|
||||||
channel if <code>channel</code> is omitted.
|
or the current channel if <code>channel</code> is
|
||||||
|
omitted.
|
||||||
</p>
|
</p>
|
||||||
<p>Aliases: <code>/close</code>, <code>/leave</code></p>
|
<p>Aliases: <code>/close</code>, <code>/leave</code></p>
|
||||||
</div>
|
</div>
|
||||||
@ -680,8 +702,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Leave and immediately rejoin the current channel. Useful to quickly get op
|
Leave and immediately rejoin the current channel. Useful
|
||||||
from ChanServ in an empty channel, for example.
|
to quickly get op from ChanServ in an empty channel, for
|
||||||
|
example.
|
||||||
</p>
|
</p>
|
||||||
<p>Alias: <code>/cycle</code></p>
|
<p>Alias: <code>/cycle</code></p>
|
||||||
</div>
|
</div>
|
||||||
@ -701,7 +724,10 @@
|
|||||||
<code>/quit [message]</code>
|
<code>/quit [message]</code>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>Disconnect from the current network with an optional message.</p>
|
<p>
|
||||||
|
Disconnect from the current network with an optional
|
||||||
|
message.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -739,8 +765,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Get the topic in the current channel. If <code>newtopic</code> is specified,
|
Get the topic in the current channel. If
|
||||||
sets the topic in the current channel.
|
<code>newtopic</code> is specified, sets the topic in
|
||||||
|
the current channel.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -751,8 +778,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Unban (<code>-b</code>) a user from the current channel. This can be a
|
Unban (<code>-b</code>) a user from the current channel.
|
||||||
nickname or a hostmask.
|
This can be a nickname or a hostmask.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -763,8 +790,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Unblock messages from the specified user on the current network. This can be
|
Unblock messages from the specified user on the current
|
||||||
a nickname or a hostmask.
|
network. This can be a nickname or a hostmask.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -775,8 +802,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Un-mutes the given channel(s) or the current channel if no channel is
|
Un-mutes the given channel(s) or the current channel if
|
||||||
provided. See <code>/mute</code> for more information.
|
no channel is provided. See <code>/mute</code> for more
|
||||||
|
information.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -787,7 +815,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>
|
<p>
|
||||||
Give voice (<code>+v</code>) to one or several users in the current channel.
|
Give voice (<code>+v</code>) to one or several users in
|
||||||
|
the current channel.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -797,7 +826,10 @@
|
|||||||
<code>/whois nick</code>
|
<code>/whois nick</code>
|
||||||
</div>
|
</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>Retrieve information about the given user on the current network.</p>
|
<p>
|
||||||
|
Retrieve information about the given user on the current
|
||||||
|
network.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -1193,8 +1225,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {defineComponent, ref} from "vue";
|
import { defineComponent, ref } from "vue";
|
||||||
import {useStore} from "../../js/store";
|
import { useStore } from "../../js/store";
|
||||||
import SidebarToggle from "../SidebarToggle.vue";
|
import SidebarToggle from "../SidebarToggle.vue";
|
||||||
import VersionChecker from "../VersionChecker.vue";
|
import VersionChecker from "../VersionChecker.vue";
|
||||||
|
|
||||||
@ -1206,7 +1238,8 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
const isApple = navigator.platform.match(/(Mac|iPhone|iPod|iPad)/i) || false;
|
const isApple =
|
||||||
|
navigator.platform.match(/(Mac|iPhone|iPod|iPad)/i) || false;
|
||||||
const isTouch = navigator.maxTouchPoints > 0;
|
const isTouch = navigator.maxTouchPoints > 0;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -1,35 +1,15 @@
|
|||||||
import constants from "./constants";
|
import constants from "./constants";
|
||||||
|
|
||||||
import Mousetrap from "mousetrap";
|
import Mousetrap from "mousetrap";
|
||||||
import {Strategy, Textcomplete, StrategyProps} from "@textcomplete/core";
|
import { Strategy, Textcomplete, StrategyProps } from "@textcomplete/core";
|
||||||
import {TextareaEditor} from "@textcomplete/textarea";
|
import { TextareaEditor } from "@textcomplete/textarea";
|
||||||
|
|
||||||
import fuzzy from "fuzzy";
|
import fuzzy from "fuzzy";
|
||||||
|
|
||||||
import emojiMap from "./helpers/simplemap.json";
|
import { store } from "./store";
|
||||||
import {store} from "./store";
|
|
||||||
|
|
||||||
export default enableAutocomplete;
|
export default enableAutocomplete;
|
||||||
|
|
||||||
const emojiSearchTerms = Object.keys(emojiMap);
|
|
||||||
const emojiStrategy: StrategyProps = {
|
|
||||||
id: "emoji",
|
|
||||||
match: /(^|\s):([-+\w:?]{2,}):?$/,
|
|
||||||
search(term: string, callback: (matches) => void) {
|
|
||||||
// Trim colon from the matched term,
|
|
||||||
// as we are unable to get a clean string from match regex
|
|
||||||
term = term.replace(/:$/, "");
|
|
||||||
callback(fuzzyGrep(term, emojiSearchTerms));
|
|
||||||
},
|
|
||||||
template([string, original]: [string, string]) {
|
|
||||||
return `<span class="emoji">${String(emojiMap[original])}</span> ${string}`;
|
|
||||||
},
|
|
||||||
replace([, original]: [string, string]) {
|
|
||||||
return "$1" + String(emojiMap[original]);
|
|
||||||
},
|
|
||||||
index: 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
const nicksStrategy: StrategyProps = {
|
const nicksStrategy: StrategyProps = {
|
||||||
id: "nicks",
|
id: "nicks",
|
||||||
match: /(^|\s)(@([a-zA-Z_[\]\\^{}|`@][a-zA-Z0-9_[\]\\^{}|`-]*)?)$/,
|
match: /(^|\s)(@([a-zA-Z_[\]\\^{}|`@][a-zA-Z0-9_[\]\\^{}|`-]*)?)$/,
|
||||||
@ -39,7 +19,12 @@ const nicksStrategy: StrategyProps = {
|
|||||||
if (term[0] === "@") {
|
if (term[0] === "@") {
|
||||||
// TODO: type
|
// TODO: type
|
||||||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
||||||
callback(completeNicks(term.slice(1), true).map((val) => ["@" + val[0], "@" + val[1]]));
|
callback(
|
||||||
|
completeNicks(term.slice(1), true).map((val) => [
|
||||||
|
"@" + val[0],
|
||||||
|
"@" + val[1],
|
||||||
|
])
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
callback(completeNicks(term, true));
|
callback(completeNicks(term, true));
|
||||||
}
|
}
|
||||||
@ -108,7 +93,9 @@ const foregroundColorStrategy: StrategyProps = {
|
|||||||
callback(matchingColorCodes);
|
callback(matchingColorCodes);
|
||||||
},
|
},
|
||||||
template(value: string[]) {
|
template(value: string[]) {
|
||||||
return `<span class="irc-fg${parseInt(value[0], 10)}">${value[1]}</span>`;
|
return `<span class="irc-fg${parseInt(value[0], 10)}">${
|
||||||
|
value[1]
|
||||||
|
}</span>`;
|
||||||
},
|
},
|
||||||
replace(value: string) {
|
replace(value: string) {
|
||||||
return "\x03" + value[0];
|
return "\x03" + value[0];
|
||||||
@ -119,7 +106,11 @@ const foregroundColorStrategy: StrategyProps = {
|
|||||||
const backgroundColorStrategy: StrategyProps = {
|
const backgroundColorStrategy: StrategyProps = {
|
||||||
id: "background-colors",
|
id: "background-colors",
|
||||||
match: /\x03(\d{2}),(\d{0,2}|[A-Za-z ]{0,10})$/,
|
match: /\x03(\d{2}),(\d{0,2}|[A-Za-z ]{0,10})$/,
|
||||||
search(term: string, callback: (matchingColorCodes: string[][]) => void, match: string[]) {
|
search(
|
||||||
|
term: string,
|
||||||
|
callback: (matchingColorCodes: string[][]) => void,
|
||||||
|
match: string[]
|
||||||
|
) {
|
||||||
term = term.toLowerCase();
|
term = term.toLowerCase();
|
||||||
const matchingColorCodes = constants.colorCodeMap
|
const matchingColorCodes = constants.colorCodeMap
|
||||||
.filter((i) => fuzzy.test(term, i[0]) || fuzzy.test(term, i[1]))
|
.filter((i) => fuzzy.test(term, i[0]) || fuzzy.test(term, i[1]))
|
||||||
@ -141,10 +132,10 @@ const backgroundColorStrategy: StrategyProps = {
|
|||||||
callback(matchingColorCodes);
|
callback(matchingColorCodes);
|
||||||
},
|
},
|
||||||
template(value: string[]) {
|
template(value: string[]) {
|
||||||
return `<span class="irc-fg${parseInt(value[2], 10)} irc-bg irc-bg${parseInt(
|
return `<span class="irc-fg${parseInt(
|
||||||
value[0],
|
value[2],
|
||||||
10
|
10
|
||||||
)}">${value[1]}</span>`;
|
)} irc-bg irc-bg${parseInt(value[0], 10)}">${value[1]}</span>`;
|
||||||
},
|
},
|
||||||
replace(value: string[]) {
|
replace(value: string[]) {
|
||||||
return "\x03$1," + value[0];
|
return "\x03$1," + value[0];
|
||||||
@ -179,7 +170,9 @@ function enableAutocomplete(input: HTMLTextAreaElement) {
|
|||||||
const text = input.value;
|
const text = input.value;
|
||||||
|
|
||||||
if (tabCount === 0) {
|
if (tabCount === 0) {
|
||||||
lastMatch = text.substring(0, input.selectionStart).split(/\s/).pop() || "";
|
lastMatch =
|
||||||
|
text.substring(0, input.selectionStart).split(/\s/).pop() ||
|
||||||
|
"";
|
||||||
|
|
||||||
if (lastMatch.length === 0) {
|
if (lastMatch.length === 0) {
|
||||||
return;
|
return;
|
||||||
@ -219,7 +212,6 @@ function enableAutocomplete(input: HTMLTextAreaElement) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const strategies = [
|
const strategies = [
|
||||||
emojiStrategy,
|
|
||||||
nicksStrategy,
|
nicksStrategy,
|
||||||
chanStrategy,
|
chanStrategy,
|
||||||
commandStrategy,
|
commandStrategy,
|
||||||
@ -261,7 +253,10 @@ function replaceNick(original: string, position = 1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If there is whitespace in the input already, append space to nick
|
// If there is whitespace in the input already, append space to nick
|
||||||
if (position > 0 && /\s/.test(store.state.activeChannel?.channel.pendingMessage || "")) {
|
if (
|
||||||
|
position > 0 &&
|
||||||
|
/\s/.test(store.state.activeChannel?.channel.pendingMessage || "")
|
||||||
|
) {
|
||||||
return original + " ";
|
return original + " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,14 +280,19 @@ function rawNicks() {
|
|||||||
if (store.state.activeChannel.channel.users.length > 0) {
|
if (store.state.activeChannel.channel.users.length > 0) {
|
||||||
const users = store.state.activeChannel.channel.users.slice();
|
const users = store.state.activeChannel.channel.users.slice();
|
||||||
|
|
||||||
return users.sort((a, b) => b.lastMessage - a.lastMessage).map((u) => u.nick);
|
return users
|
||||||
|
.sort((a, b) => b.lastMessage - a.lastMessage)
|
||||||
|
.map((u) => u.nick);
|
||||||
}
|
}
|
||||||
|
|
||||||
const me = store.state.activeChannel.network.nick;
|
const me = store.state.activeChannel.network.nick;
|
||||||
const otherUser = store.state.activeChannel.channel.name;
|
const otherUser = store.state.activeChannel.channel.name;
|
||||||
|
|
||||||
// If this is a query, add their name to autocomplete
|
// If this is a query, add their name to autocomplete
|
||||||
if (me !== otherUser && store.state.activeChannel.channel.type === "query") {
|
if (
|
||||||
|
me !== otherUser &&
|
||||||
|
store.state.activeChannel.channel.type === "query"
|
||||||
|
) {
|
||||||
return [otherUser, me];
|
return [otherUser, me];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
services:
|
services:
|
||||||
hardlounge:
|
hardlounge:
|
||||||
image: git.supernets.org/supernets/hardlounge:latest
|
image: git.supernets.org/supernets/hardlounge:latest
|
||||||
#build: .
|
build: .
|
||||||
ports:
|
ports:
|
||||||
- "9000:9000"
|
- "9000:9000"
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {expect} from "chai";
|
import { expect } from "chai";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
@ -6,68 +6,102 @@ describe("public folder", function () {
|
|||||||
const publicFolder = path.join(__dirname, "..", "..", "public");
|
const publicFolder = path.join(__dirname, "..", "..", "public");
|
||||||
|
|
||||||
it("font awesome files are copied", function () {
|
it("font awesome files are copied", function () {
|
||||||
expect(fs.existsSync(path.join(publicFolder, "fonts", "fa-solid-900.woff"))).to.be.true;
|
expect(
|
||||||
expect(fs.existsSync(path.join(publicFolder, "fonts", "fa-solid-900.woff2"))).to.be.true;
|
fs.existsSync(path.join(publicFolder, "fonts", "fa-solid-900.woff"))
|
||||||
|
).to.be.true;
|
||||||
|
expect(
|
||||||
|
fs.existsSync(
|
||||||
|
path.join(publicFolder, "fonts", "fa-solid-900.woff2")
|
||||||
|
)
|
||||||
|
).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
it("files in root folder are copied", function () {
|
it("files in root folder are copied", function () {
|
||||||
expect(fs.existsSync(path.join(publicFolder, "favicon.ico"))).to.be.true;
|
expect(fs.existsSync(path.join(publicFolder, "favicon.ico"))).to.be
|
||||||
|
.true;
|
||||||
expect(fs.existsSync(path.join(publicFolder, "robots.txt"))).to.be.true;
|
expect(fs.existsSync(path.join(publicFolder, "robots.txt"))).to.be.true;
|
||||||
expect(fs.existsSync(path.join(publicFolder, "service-worker.js"))).to.be.true;
|
expect(fs.existsSync(path.join(publicFolder, "service-worker.js"))).to
|
||||||
expect(fs.existsSync(path.join(publicFolder, "thelounge.webmanifest"))).to.be.true;
|
.be.true;
|
||||||
|
expect(fs.existsSync(path.join(publicFolder, "thelounge.webmanifest")))
|
||||||
|
.to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
it("audio files are copied", function () {
|
it("audio files are copied", function () {
|
||||||
expect(fs.existsSync(path.join(publicFolder, "audio", "pop.wav"))).to.be.true;
|
expect(fs.existsSync(path.join(publicFolder, "audio", "pop.wav"))).to.be
|
||||||
});
|
|
||||||
|
|
||||||
it("index HTML file is not copied", function () {
|
|
||||||
expect(fs.existsSync(path.join(publicFolder, "index.html"))).to.be.false;
|
|
||||||
expect(fs.existsSync(path.join(publicFolder, "index.html.tpl"))).to.be.false;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("javascript files are built", function () {
|
|
||||||
expect(fs.existsSync(path.join(publicFolder, "js", "bundle.js"))).to.be.true;
|
|
||||||
expect(fs.existsSync(path.join(publicFolder, "js", "bundle.vendor.js"))).to.be.true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("style files are built", function () {
|
|
||||||
expect(fs.existsSync(path.join(publicFolder, "css", "style.css"))).to.be.true;
|
|
||||||
expect(fs.existsSync(path.join(publicFolder, "css", "style.css.map"))).to.be.true;
|
|
||||||
expect(fs.existsSync(path.join(publicFolder, "themes", "default.css"))).to.be.true;
|
|
||||||
expect(fs.existsSync(path.join(publicFolder, "themes", "morning.css"))).to.be.true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("style files contain expected content", function (done) {
|
|
||||||
fs.readFile(path.join(publicFolder, "css", "style.css"), "utf8", function (err, contents) {
|
|
||||||
expect(err).to.be.null;
|
|
||||||
|
|
||||||
expect(contents.includes("var(--body-color)")).to.be.true;
|
|
||||||
expect(contents.includes("url(../fonts/fa-solid-900.woff2)")).to.be.true;
|
|
||||||
expect(contents.includes(".tooltipped{position:relative}")).to.be.true;
|
|
||||||
expect(contents.includes("sourceMappingURL")).to.be.true;
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("javascript map is created", function () {
|
|
||||||
expect(fs.existsSync(path.join(publicFolder, "js", "bundle.js.map"))).to.be.true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("loading-error-handlers.js is copied", function () {
|
|
||||||
expect(fs.existsSync(path.join(publicFolder, "js", "loading-error-handlers.js"))).to.be
|
|
||||||
.true;
|
.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("index HTML file is not copied", function () {
|
||||||
|
expect(fs.existsSync(path.join(publicFolder, "index.html"))).to.be
|
||||||
|
.false;
|
||||||
|
expect(fs.existsSync(path.join(publicFolder, "index.html.tpl"))).to.be
|
||||||
|
.false;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("javascript files are built", function () {
|
||||||
|
expect(fs.existsSync(path.join(publicFolder, "js", "bundle.js"))).to.be
|
||||||
|
.true;
|
||||||
|
expect(fs.existsSync(path.join(publicFolder, "js", "bundle.vendor.js")))
|
||||||
|
.to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("style files are built", function () {
|
||||||
|
expect(fs.existsSync(path.join(publicFolder, "css", "style.css"))).to.be
|
||||||
|
.true;
|
||||||
|
expect(fs.existsSync(path.join(publicFolder, "css", "style.css.map")))
|
||||||
|
.to.be.true;
|
||||||
|
expect(fs.existsSync(path.join(publicFolder, "themes", "default.css")))
|
||||||
|
.to.be.true;
|
||||||
|
expect(fs.existsSync(path.join(publicFolder, "themes", "morning.css")))
|
||||||
|
.to.be.true;
|
||||||
|
expect(fs.existsSync(path.join(publicFolder, "themes", "oled.css"))).to
|
||||||
|
.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("style files contain expected content", function (done) {
|
||||||
|
fs.readFile(
|
||||||
|
path.join(publicFolder, "css", "style.css"),
|
||||||
|
"utf8",
|
||||||
|
function (err, contents) {
|
||||||
|
expect(err).to.be.null;
|
||||||
|
|
||||||
|
expect(contents.includes("var(--body-color)")).to.be.true;
|
||||||
|
expect(contents.includes("url(../fonts/fa-solid-900.woff2)")).to
|
||||||
|
.be.true;
|
||||||
|
expect(contents.includes(".tooltipped{position:relative}")).to
|
||||||
|
.be.true;
|
||||||
|
expect(contents.includes("sourceMappingURL")).to.be.true;
|
||||||
|
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("javascript map is created", function () {
|
||||||
|
expect(fs.existsSync(path.join(publicFolder, "js", "bundle.js.map"))).to
|
||||||
|
.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("loading-error-handlers.js is copied", function () {
|
||||||
|
expect(
|
||||||
|
fs.existsSync(
|
||||||
|
path.join(publicFolder, "js", "loading-error-handlers.js")
|
||||||
|
)
|
||||||
|
).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
it("service worker has cacheName set", function (done) {
|
it("service worker has cacheName set", function (done) {
|
||||||
fs.readFile(path.join(publicFolder, "service-worker.js"), "utf8", function (err, contents) {
|
fs.readFile(
|
||||||
expect(err).to.be.null;
|
path.join(publicFolder, "service-worker.js"),
|
||||||
|
"utf8",
|
||||||
|
function (err, contents) {
|
||||||
|
expect(err).to.be.null;
|
||||||
|
|
||||||
expect(contents.includes("const cacheName")).to.be.true;
|
expect(contents.includes("const cacheName")).to.be.true;
|
||||||
expect(contents.includes("__HASH__")).to.be.false;
|
expect(contents.includes("__HASH__")).to.be.false;
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user