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