Merge pull request #3574 from thelounge/xpaw/normalize.css

Remove bootstrap.css, use flexbox
This commit is contained in:
Pavel Djundik 2019-12-14 22:37:37 +02:00 committed by GitHub
commit ead372e6e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 694 additions and 1887 deletions

View File

@ -1,6 +1,6 @@
<template> <template>
<div ref="chat" class="chat" tabindex="-1"> <div ref="chat" class="chat" tabindex="-1">
<div :class="['show-more', {show: channel.moreHistoryAvailable}]"> <div v-show="channel.moreHistoryAvailable" class="show-more">
<button <button
ref="loadMoreButton" ref="loadMoreButton"
:disabled="channel.historyLoading || !$store.state.isConnected" :disabled="channel.historyLoading || !$store.state.isConnected"

View File

@ -4,193 +4,160 @@
<SidebarToggle /> <SidebarToggle />
</div> </div>
<form class="container" method="post" action="" @submit.prevent="onSubmit"> <form class="container" method="post" action="" @submit.prevent="onSubmit">
<div class="row"> <h1 class="title">
<div class="col-sm-12"> <template v-if="defaults.uuid">
<h1 class="title"> <input type="hidden" name="uuid" :value="defaults.uuid" />
<template v-if="defaults.uuid"> Edit {{ defaults.name }}
<input type="hidden" name="uuid" :value="defaults.uuid" />
Edit {{ defaults.name }}
</template>
<template v-else>
<template v-if="config.public">The Lounge - </template>
Connect
<template v-if="!config.displayNetwork">
<template v-if="config.lockNetwork">
to {{ defaults.name }}
</template>
</template>
</template>
</h1>
</div>
<template v-if="config.displayNetwork">
<div>
<div class="col-sm-12">
<h2>Network settings</h2>
</div>
<div class="col-sm-3">
<label for="connect:name">Name</label>
</div>
<div class="col-sm-9">
<input
id="connect:name"
class="input"
name="name"
:value="defaults.name"
maxlength="100"
/>
</div>
<div class="col-sm-3">
<label for="connect:host">Server</label>
</div>
<div class="col-sm-6 col-xs-8">
<input
id="connect:host"
class="input"
name="host"
:value="defaults.host"
aria-label="Server address"
maxlength="255"
required
:disabled="config.lockNetwork ? true : false"
/>
</div>
<div class="col-sm-3 col-xs-4">
<div class="port">
<input
class="input"
type="number"
min="1"
max="65535"
name="port"
:value="defaults.port"
aria-label="Server port"
:disabled="config.lockNetwork ? true : false"
/>
</div>
</div>
<div class="clearfix" />
<div class="col-sm-9 col-sm-offset-3">
<label class="tls">
<input
type="checkbox"
name="tls"
:checked="defaults.tls ? true : false"
:disabled="config.lockNetwork ? true : false"
/>
Use secure connection (TLS)
</label>
</div>
<div class="col-sm-9 col-sm-offset-3">
<label class="tls">
<input
type="checkbox"
name="rejectUnauthorized"
:checked="defaults.rejectUnauthorized ? true : false"
:disabled="config.lockNetwork ? true : false"
/>
Only allow trusted certificates
</label>
</div>
<div class="clearfix" />
</div>
</template> </template>
<div class="col-sm-12"> <template v-else>
<h2>User preferences</h2> <template v-if="config.public">The Lounge - </template>
</div> Connect
<div class="col-sm-3"> <template v-if="!config.displayNetwork">
<label for="connect:nick">Nick</label> <template v-if="config.lockNetwork"> to {{ defaults.name }} </template>
</div> </template>
<div class="col-sm-9"> </template>
</h1>
<template v-if="config.displayNetwork">
<h2>Network settings</h2>
<div class="connect-row">
<label for="connect:name">Name</label>
<input <input
id="connect:nick" id="connect:name"
class="input nick" class="input"
name="nick" name="name"
:value="defaults.nick" :value="defaults.name"
maxlength="100" maxlength="100"
required
@input="onNickChanged"
/> />
</div> </div>
<template v-if="!config.useHexIp"> <div class="connect-row">
<div class="col-sm-3"> <label for="connect:host">Server</label>
<label for="connect:username">Username</label> <div class="input-wrap">
</div>
<div class="col-sm-9">
<input <input
id="connect:username" id="connect:host"
ref="usernameInput"
class="input username"
name="username"
:value="defaults.username"
maxlength="512"
/>
</div>
</template>
<div class="col-sm-3">
<label for="connect:password">Password</label>
</div>
<div class="col-sm-9 password-container">
<RevealPassword v-slot:default="slotProps">
<input
id="connect:password"
v-model="defaults.password"
class="input" class="input"
:type="slotProps.isVisible ? 'text' : 'password'" name="host"
name="password" :value="defaults.host"
maxlength="512" aria-label="Server address"
maxlength="255"
required
:disabled="config.lockNetwork ? true : false"
/> />
</RevealPassword> <span id="connect:portseparator">:</span>
<input
id="connect:port"
class="input"
type="number"
min="1"
max="65535"
name="port"
:value="defaults.port"
aria-label="Server port"
:disabled="config.lockNetwork ? true : false"
/>
</div>
</div> </div>
<div class="col-sm-3"> <div class="connect-row">
<label for="connect:realname">Real name</label> <label></label>
<div class="input-wrap">
<label class="tls">
<input
type="checkbox"
name="tls"
:checked="defaults.tls ? true : false"
:disabled="config.lockNetwork ? true : false"
/>
Use secure connection (TLS)
</label>
<label class="tls">
<input
type="checkbox"
name="rejectUnauthorized"
:checked="defaults.rejectUnauthorized ? true : false"
:disabled="config.lockNetwork ? true : false"
/>
Only allow trusted certificates
</label>
</div>
</div> </div>
<div class="col-sm-9"> </template>
<h2>User preferences</h2>
<div class="connect-row">
<label for="connect:nick">Nick</label>
<input
id="connect:nick"
class="input nick"
name="nick"
:value="defaults.nick"
maxlength="100"
required
@input="onNickChanged"
/>
</div>
<template v-if="!config.useHexIp">
<div class="connect-row">
<label for="connect:username">Username</label>
<input <input
id="connect:realname" id="connect:username"
class="input" ref="usernameInput"
name="realname" class="input username"
:value="defaults.realname" name="username"
:value="defaults.username"
maxlength="512" maxlength="512"
/> />
</div> </div>
<template v-if="defaults.uuid"> </template>
<div class="col-sm-3"> <div class="connect-row">
<label for="connect:commands">Commands</label> <label for="connect:password">Password</label>
</div> <RevealPassword v-slot:default="slotProps" class="input-wrap password-container">
<div class="col-sm-9"> <input
<textarea id="connect:password"
id="connect:commands" v-model="defaults.password"
class="input" class="input"
name="commands" :type="slotProps.isVisible ? 'text' : 'password'"
placeholder="One raw command per line, each command will be executed on new connection" name="password"
:value="defaults.commands ? defaults.commands.join('\n') : ''" maxlength="512"
/> />
</div> </RevealPassword>
<div class="col-sm-9 col-sm-offset-3">
<button type="submit" class="btn" :disabled="disabled ? true : false">
Save
</button>
</div>
</template>
<template v-else>
<div class="col-sm-3">
<label for="connect:channels">Channels</label>
</div>
<div class="col-sm-9">
<input
id="connect:channels"
class="input"
name="join"
:value="defaults.join"
/>
</div>
<div class="col-sm-9 col-sm-offset-3">
<button type="submit" class="btn" :disabled="disabled ? true : false">
Connect
</button>
</div>
</template>
</div> </div>
<div class="connect-row">
<label for="connect:realname">Real name</label>
<input
id="connect:realname"
class="input"
name="realname"
:value="defaults.realname"
maxlength="512"
/>
</div>
<template v-if="defaults.uuid">
<div class="connect-row">
<label for="connect:commands">Commands</label>
<textarea
id="connect:commands"
class="input"
name="commands"
placeholder="One raw command per line, each command will be executed on new connection"
:value="defaults.commands ? defaults.commands.join('\n') : ''"
/>
</div>
<div>
<button type="submit" class="btn" :disabled="disabled ? true : false">
Save
</button>
</div>
</template>
<template v-else>
<div class="connect-row">
<label for="connect:channels">Channels</label>
<input id="connect:channels" class="input" name="join" :value="defaults.join" />
</div>
<div>
<button type="submit" class="btn" :disabled="disabled ? true : false">
Connect
</button>
</div>
</template>
</form> </form>
</div> </div>
</template> </template>

View File

@ -1,30 +1,28 @@
<template> <template>
<p> <div class="session-item">
<button class="btn pull-right remove-session" @click.prevent="signOut"> <div class="session-item-info">
<template v-if="session.current"> <strong>{{ session.agent }}</strong>
Sign out
</template>
<template v-else>
Revoke
</template>
</button>
<strong>{{ session.agent }}</strong> <a :href="'https://ipinfo.io/' + session.ip" target="_blank" rel="noopener">{{
session.ip
}}</a>
<a :href="'https://ipinfo.io/' + session.ip" target="_blank" rel="noopener">{{ <template v-if="!session.current">
session.ip <p v-if="session.active">
}}</a> <em>Currently active</em>
</p>
<template v-if="!session.current"> <p v-else>
<br /> Last used on <time>{{ session.lastUse | localetime }}</time>
<template v-if="session.active"> </p>
<em>Currently active</em>
</template> </template>
<template v-else> </div>
Last used on <time>{{ session.lastUse | localetime }}</time> <div class="session-item-btn">
</template> <button class="btn" @click.prevent="signOut">
</template> <template v-if="session.current">Sign out</template>
</p> <template v-else>Revoke</template>
</button>
</div>
</div>
</template> </template>
<script> <script>

View File

@ -6,15 +6,15 @@
<div class="container"> <div class="container">
<h1 class="title">Help</h1> <h1 class="title">Help</h1>
<h2> <h2 class="help-version-title">
<small class="pull-right"> <span>About The Lounge</span>
<small>
v{{ $store.state.serverConfiguration.version }} (<router-link v{{ $store.state.serverConfiguration.version }} (<router-link
id="view-changelog" id="view-changelog"
to="/changelog" to="/changelog"
>release notes</router-link >release notes</router-link
>) >)
</small> </small>
About The Lounge
</h2> </h2>
<div class="about"> <div class="about">

View File

@ -6,471 +6,427 @@
<form ref="settingsForm" class="container" @change="onChange" @submit.prevent> <form ref="settingsForm" class="container" @change="onChange" @submit.prevent>
<h1 class="title">Settings</h1> <h1 class="title">Settings</h1>
<div class="row"> <div>
<div class="col-sm-6"> <label class="opt">
<input
:checked="$store.state.settings.advanced"
type="checkbox"
name="advanced"
/>
Advanced settings
</label>
</div>
<div v-if="canRegisterProtocol || hasInstallPromptEvent">
<h2>Native app</h2>
<button
v-if="hasInstallPromptEvent"
type="button"
class="btn"
@click.prevent="nativeInstallPrompt"
>
Add The Lounge to Home screen
</button>
<button
v-if="canRegisterProtocol"
type="button"
class="btn"
@click.prevent="registerProtocol"
>
Open irc:// URLs with The Lounge
</button>
</div>
<div v-if="!$store.state.serverConfiguration.public && $store.state.settings.advanced">
<h2>Settings synchronisation</h2>
<label class="opt">
<input
:checked="$store.state.settings.syncSettings"
type="checkbox"
name="syncSettings"
/>
Synchronize settings with other clients
</label>
<template v-if="!$store.state.settings.syncSettings">
<div v-if="$store.state.serverHasSettings" class="settings-sync-panel">
<p>
<strong>Warning:</strong> Checking this box will override the settings
of this client with those stored on the server.
</p>
<p>
Use the button below to enable synchronization, and override any
settings already synced to the server.
</p>
<button type="button" class="btn btn-small" @click="onForceSyncClick">
Sync settings and enable
</button>
</div>
<div v-else class="settings-sync-panel">
<p>
<strong>Warning:</strong> No settings have been synced before. Enabling
this will sync all settings of this client as the base for other
clients.
</p>
</div>
</template>
</div>
<h2>Messages</h2>
<div>
<label class="opt">
<input :checked="$store.state.settings.motd" type="checkbox" name="motd" />
Show <abbr title="Message Of The Day">MOTD</abbr>
</label>
</div>
<div>
<label class="opt">
<input
:checked="$store.state.settings.showSeconds"
type="checkbox"
name="showSeconds"
/>
Show seconds in timestamp
</label>
</div>
<div v-if="$store.state.settings.advanced">
<h2>Automatic away message</h2>
<label class="opt">
<label for="awayMessage" class="sr-only">Automatic away message</label>
<input
id="awayMessage"
:value="$store.state.settings.awayMessage"
type="text"
name="awayMessage"
class="input"
placeholder="Away message if The Lounge is not open"
/>
</label>
</div>
<h2>
Status messages
<span
class="tooltipped tooltipped-n tooltipped-no-delay"
aria-label="Joins, parts, kicks, nick changes, away changes, and mode changes"
>
<button
class="extra-help"
aria-label="Joins, parts, kicks, nick changes, away changes, and mode changes"
/>
</span>
</h2>
<div>
<label class="opt">
<input
:checked="$store.state.settings.statusMessages === 'shown'"
type="radio"
name="statusMessages"
value="shown"
/>
Show all status messages individually
</label>
<label class="opt">
<input
:checked="$store.state.settings.statusMessages === 'condensed'"
type="radio"
name="statusMessages"
value="condensed"
/>
Condense status messages together
</label>
<label class="opt">
<input
:checked="$store.state.settings.statusMessages === 'hidden'"
type="radio"
name="statusMessages"
value="hidden"
/>
Hide all status messages
</label>
</div>
<h2>Visual Aids</h2>
<div>
<label class="opt">
<input
:checked="$store.state.settings.coloredNicks"
type="checkbox"
name="coloredNicks"
/>
Enable colored nicknames
</label>
<label class="opt">
<input
:checked="$store.state.settings.autocomplete"
type="checkbox"
name="autocomplete"
/>
Enable autocomplete
</label>
</div>
<div v-if="$store.state.settings.advanced">
<label class="opt">
<label for="nickPostfix" class="sr-only">
Nick autocomplete postfix (e.g. <code>, </code>)
</label>
<input
id="nickPostfix"
:value="$store.state.settings.nickPostfix"
type="text"
name="nickPostfix"
class="input"
placeholder="Nick autocomplete postfix (e.g. ', ')"
/>
</label>
</div>
<h2>Theme</h2>
<div>
<label for="theme-select" class="sr-only">Theme</label>
<select
id="theme-select"
:value="$store.state.settings.theme"
name="theme"
class="input"
>
<option
v-for="theme in $store.state.serverConfiguration.themes"
:key="theme.name"
:value="theme.name"
>
{{ theme.displayName }}
</option>
</select>
</div>
<template v-if="$store.state.serverConfiguration.prefetch">
<h2>Link previews</h2>
<div>
<label class="opt"> <label class="opt">
<input <input
:checked="$store.state.settings.advanced" :checked="$store.state.settings.media"
type="checkbox" type="checkbox"
name="advanced" name="media"
/> />
Advanced settings Auto-expand media
</label> </label>
</div> </div>
<div>
<label class="opt">
<input
:checked="$store.state.settings.links"
type="checkbox"
name="links"
/>
Auto-expand websites
</label>
</div>
</template>
<template v-if="!$store.state.serverConfiguration.public">
<h2>Push Notifications</h2>
<div>
<button
id="pushNotifications"
type="button"
class="btn"
:disabled="
$store.state.pushNotificationState !== 'supported' &&
$store.state.pushNotificationState !== 'subscribed'
"
@click="onPushButtonClick"
>
<template v-if="$store.state.pushNotificationState === 'subscribed'">
Unsubscribe from push notifications
</template>
<template v-else-if="$store.state.pushNotificationState === 'loading'">
Loading
</template>
<template v-else>
Subscribe to push notifications
</template>
</button>
<div v-if="$store.state.pushNotificationState === 'nohttps'" class="error">
<strong>Warning</strong>: Push notifications are only supported over HTTPS
connections.
</div>
<div v-if="$store.state.pushNotificationState === 'unsupported'" class="error">
<strong>Warning</strong>:
<span>Push notifications are not supported by your browser.</span>
</div>
</div>
</template>
<h2>Browser Notifications</h2>
<div>
<label class="opt">
<input
id="desktopNotifications"
:checked="$store.state.settings.desktopNotifications"
type="checkbox"
name="desktopNotifications"
/>
Enable browser notifications<br />
<div
v-if="$store.state.desktopNotificationState === 'unsupported'"
class="error"
>
<strong>Warning</strong>: Notifications are not supported by your browser.
</div>
<div
v-if="$store.state.desktopNotificationState === 'blocked'"
id="warnBlockedDesktopNotifications"
class="error"
>
<strong>Warning</strong>: Notifications are blocked by your browser.
</div>
</label>
</div>
<div>
<label class="opt">
<input
:checked="$store.state.settings.notification"
type="checkbox"
name="notification"
/>
Enable notification sound
</label>
</div>
<div>
<div class="opt">
<button id="play" @click.prevent="playNotification">Play sound</button>
</div>
</div> </div>
<div class="row"> <div v-if="$store.state.settings.advanced">
<div v-if="canRegisterProtocol || hasInstallPromptEvent" class="col-sm-12"> <label class="opt">
<h2>Native app</h2> <input
<button :checked="$store.state.settings.notifyAllMessages"
v-if="hasInstallPromptEvent" type="checkbox"
type="button" name="notifyAllMessages"
class="btn"
@click.prevent="nativeInstallPrompt"
>
Add The Lounge to Home screen
</button>
<button
v-if="canRegisterProtocol"
type="button"
class="btn"
@click.prevent="registerProtocol"
>
Open irc:// URLs with The Lounge
</button>
</div>
<div
v-if="
!$store.state.serverConfiguration.public && $store.state.settings.advanced
"
class="col-sm-12"
>
<h2>
Settings synchronisation
<span
class="tooltipped tooltipped-n tooltipped-no-delay"
aria-label="Note: This is an experimental feature and may change in future releases."
>
<button
class="extra-experimental"
aria-label="Note: This is an experimental feature and may change in future releases."
/>
</span>
</h2>
<label class="opt">
<input
:checked="$store.state.settings.syncSettings"
type="checkbox"
name="syncSettings"
/>
Synchronize settings with other clients
</label>
<template v-if="!$store.state.settings.syncSettings">
<div v-if="$store.state.serverHasSettings" class="settings-sync-panel">
<p>
<strong>Warning:</strong> Checking this box will override the
settings of this client with those stored on the server.
</p>
<p>
Use the button below to enable synchronization, and override any
settings already synced to the server.
</p>
<button type="button" class="btn btn-small" @click="onForceSyncClick">
Sync settings and enable
</button>
</div>
<div v-else class="settings-sync-panel">
<p>
<strong>Warning:</strong> No settings have been synced before.
Enabling this will sync all settings of this client as the base for
other clients.
</p>
</div>
</template>
</div>
<div class="col-sm-12">
<h2>Messages</h2>
</div>
<div class="col-sm-6">
<label class="opt">
<input :checked="$store.state.settings.motd" type="checkbox" name="motd" />
Show <abbr title="Message Of The Day">MOTD</abbr>
</label>
</div>
<div class="col-sm-6">
<label class="opt">
<input
:checked="$store.state.settings.showSeconds"
type="checkbox"
name="showSeconds"
/>
Show seconds in timestamp
</label>
</div>
<div v-if="$store.state.settings.advanced" class="col-sm-12">
<h2>Automatic away message</h2>
<label class="opt">
<label for="awayMessage" class="sr-only">Automatic away message</label>
<input
id="awayMessage"
:value="$store.state.settings.awayMessage"
type="text"
name="awayMessage"
class="input"
placeholder="Away message if The Lounge is not open"
/>
</label>
</div>
<div class="col-sm-12">
<h2>
Status messages
<span
class="tooltipped tooltipped-n tooltipped-no-delay"
aria-label="Joins, parts, kicks, nick changes, away changes, and mode changes"
>
<button
class="extra-help"
aria-label="Joins, parts, kicks, nick changes, away changes, and mode changes"
/>
</span>
</h2>
</div>
<div class="col-sm-12">
<label class="opt">
<input
:checked="$store.state.settings.statusMessages === 'shown'"
type="radio"
name="statusMessages"
value="shown"
/>
Show all status messages individually
</label>
<label class="opt">
<input
:checked="$store.state.settings.statusMessages === 'condensed'"
type="radio"
name="statusMessages"
value="condensed"
/>
Condense status messages together
</label>
<label class="opt">
<input
:checked="$store.state.settings.statusMessages === 'hidden'"
type="radio"
name="statusMessages"
value="hidden"
/>
Hide all status messages
</label>
</div>
<div class="col-sm-12">
<h2>Visual Aids</h2>
</div>
<div class="col-sm-12">
<label class="opt">
<input
:checked="$store.state.settings.coloredNicks"
type="checkbox"
name="coloredNicks"
/>
Enable colored nicknames
</label>
<label class="opt">
<input
:checked="$store.state.settings.autocomplete"
type="checkbox"
name="autocomplete"
/>
Enable autocomplete
</label>
</div>
<div v-if="$store.state.settings.advanced" class="col-sm-12">
<label class="opt">
<label for="nickPostfix" class="sr-only">
Nick autocomplete postfix (e.g. <code>, </code>)
</label>
<input
id="nickPostfix"
:value="$store.state.settings.nickPostfix"
type="text"
name="nickPostfix"
class="input"
placeholder="Nick autocomplete postfix (e.g. ', ')"
/>
</label>
</div>
<div class="col-sm-12">
<h2>Theme</h2>
</div>
<div class="col-sm-12">
<label for="theme-select" class="sr-only">Theme</label>
<select
id="theme-select"
:value="$store.state.settings.theme"
name="theme"
class="input"
>
<option
v-for="theme in $store.state.serverConfiguration.themes"
:key="theme.name"
:value="theme.name"
>
{{ theme.displayName }}
</option>
</select>
</div>
<template v-if="$store.state.serverConfiguration.prefetch">
<div class="col-sm-12">
<h2>Link previews</h2>
</div>
<div class="col-sm-6">
<label class="opt">
<input
:checked="$store.state.settings.media"
type="checkbox"
name="media"
/>
Auto-expand media
</label>
</div>
<div class="col-sm-6">
<label class="opt">
<input
:checked="$store.state.settings.links"
type="checkbox"
name="links"
/>
Auto-expand websites
</label>
</div>
</template>
<template v-if="!$store.state.serverConfiguration.public">
<div class="col-sm-12">
<h2>Push Notifications</h2>
</div>
<div class="col-sm-12">
<button
id="pushNotifications"
type="button"
class="btn"
:disabled="
$store.state.pushNotificationState !== 'supported' &&
$store.state.pushNotificationState !== 'subscribed'
"
@click="onPushButtonClick"
>
<template v-if="$store.state.pushNotificationState === 'subscribed'">
Unsubscribe from push notifications
</template>
<template v-else-if="$store.state.pushNotificationState === 'loading'">
Loading
</template>
<template v-else>
Subscribe to push notifications
</template>
</button>
<div v-if="$store.state.pushNotificationState === 'nohttps'" class="error">
<strong>Warning</strong>: Push notifications are only supported over
HTTPS connections.
</div>
<div
v-if="$store.state.pushNotificationState === 'unsupported'"
class="error"
>
<strong>Warning</strong>:
<span>Push notifications are not supported by your browser.</span>
</div>
</div>
</template>
<div class="col-sm-12">
<h2>Browser Notifications</h2>
</div>
<div class="col-sm-12">
<label class="opt">
<input
id="desktopNotifications"
:checked="$store.state.settings.desktopNotifications"
type="checkbox"
name="desktopNotifications"
/>
Enable browser notifications<br />
<div
v-if="$store.state.desktopNotificationState === 'unsupported'"
class="error"
>
<strong>Warning</strong>: Notifications are not supported by your
browser.
</div>
<div
v-if="$store.state.desktopNotificationState === 'blocked'"
id="warnBlockedDesktopNotifications"
class="error"
>
<strong>Warning</strong>: Notifications are blocked by your browser.
</div>
</label>
</div>
<div class="col-sm-12">
<label class="opt">
<input
:checked="$store.state.settings.notification"
type="checkbox"
name="notification"
/>
Enable notification sound
</label>
</div>
<div class="col-sm-12">
<div class="opt">
<button id="play" @click.prevent="playNotification">Play sound</button>
</div>
</div>
<div v-if="$store.state.settings.advanced" class="col-sm-12">
<label class="opt">
<input
:checked="$store.state.settings.notifyAllMessages"
type="checkbox"
name="notifyAllMessages"
/>
Enable notification for all messages
</label>
</div>
<div v-if="$store.state.settings.advanced" class="col-sm-12">
<label class="opt">
<label for="highlights" class="sr-only">
Custom highlights (comma-separated keywords)
</label>
<input
id="highlights"
:value="$store.state.settings.highlights"
type="text"
name="highlights"
class="input"
placeholder="Custom highlights (comma-separated keywords)"
/>
</label>
</div>
<div
v-if="
!$store.state.serverConfiguration.public &&
!$store.state.serverConfiguration.ldapEnabled
"
id="change-password"
>
<div class="col-sm-12">
<h2>Change password</h2>
</div>
<div class="col-sm-12 password-container">
<label for="old_password_input" class="sr-only">
Enter current password
</label>
<RevealPassword v-slot:default="slotProps">
<input
id="old_password_input"
:type="slotProps.isVisible ? 'text' : 'password'"
name="old_password"
class="input"
placeholder="Enter current password"
/>
</RevealPassword>
</div>
<div class="col-sm-12 password-container">
<label for="new_password_input" class="sr-only">
Enter desired new password
</label>
<RevealPassword v-slot:default="slotProps">
<input
id="new_password_input"
:type="slotProps.isVisible ? 'text' : 'password'"
name="new_password"
class="input"
placeholder="Enter desired new password"
/>
</RevealPassword>
</div>
<div class="col-sm-12 password-container">
<label for="verify_password_input" class="sr-only">
Repeat new password
</label>
<RevealPassword v-slot:default="slotProps">
<input
id="verify_password_input"
:type="slotProps.isVisible ? 'text' : 'password'"
name="verify_password"
class="input"
placeholder="Repeat new password"
/>
</RevealPassword>
</div>
<div
v-if="passwordChangeStatus && passwordChangeStatus.success"
class="col-sm-12 feedback success"
>
Successfully updated your password
</div>
<div
v-else-if="passwordChangeStatus && passwordChangeStatus.error"
class="col-sm-12 feedback error"
>
{{ passwordErrors[passwordChangeStatus.error] }}
</div>
<div class="col-sm-12">
<button type="submit" class="btn" @click.prevent="changePassword">
Change password
</button>
</div>
</div>
<div v-if="$store.state.settings.advanced" class="col-sm-12">
<h2>Custom Stylesheet</h2>
</div>
<div v-if="$store.state.settings.advanced" class="col-sm-12">
<label for="user-specified-css-input" class="sr-only">
Custom stylesheet. You can override any style with CSS here.
</label>
<textarea
id="user-specified-css-input"
:value="$store.state.settings.userStyles"
class="input"
name="userStyles"
placeholder="/* You can override any style with CSS here */"
/> />
Enable notification for all messages
</label>
</div>
<div v-if="$store.state.settings.advanced">
<label class="opt">
<label for="highlights" class="sr-only">
Custom highlights (comma-separated keywords)
</label>
<input
id="highlights"
:value="$store.state.settings.highlights"
type="text"
name="highlights"
class="input"
placeholder="Custom highlights (comma-separated keywords)"
/>
</label>
</div>
<div
v-if="
!$store.state.serverConfiguration.public &&
!$store.state.serverConfiguration.ldapEnabled
"
id="change-password"
>
<h2>Change password</h2>
<div class="password-container">
<label for="old_password_input" class="sr-only">
Enter current password
</label>
<RevealPassword v-slot:default="slotProps">
<input
id="old_password_input"
:type="slotProps.isVisible ? 'text' : 'password'"
name="old_password"
class="input"
placeholder="Enter current password"
/>
</RevealPassword>
</div> </div>
<div class="password-container">
<label for="new_password_input" class="sr-only">
Enter desired new password
</label>
<RevealPassword v-slot:default="slotProps">
<input
id="new_password_input"
:type="slotProps.isVisible ? 'text' : 'password'"
name="new_password"
class="input"
placeholder="Enter desired new password"
/>
</RevealPassword>
</div>
<div class="password-container">
<label for="verify_password_input" class="sr-only">
Repeat new password
</label>
<RevealPassword v-slot:default="slotProps">
<input
id="verify_password_input"
:type="slotProps.isVisible ? 'text' : 'password'"
name="verify_password"
class="input"
placeholder="Repeat new password"
/>
</RevealPassword>
</div>
<div
v-if="passwordChangeStatus && passwordChangeStatus.success"
class="feedback success"
>
Successfully updated your password
</div>
<div
v-else-if="passwordChangeStatus && passwordChangeStatus.error"
class="feedback error"
>
{{ passwordErrors[passwordChangeStatus.error] }}
</div>
<div>
<button type="submit" class="btn" @click.prevent="changePassword">
Change password
</button>
</div>
</div>
<div v-if="$store.state.settings.advanced">
<h2>Custom Stylesheet</h2>
<label for="user-specified-css-input" class="sr-only">
Custom stylesheet. You can override any style with CSS here.
</label>
<textarea
id="user-specified-css-input"
:value="$store.state.settings.userStyles"
class="input"
name="userStyles"
placeholder="/* You can override any style with CSS here */"
/>
</div> </div>
<div v-if="!$store.state.serverConfiguration.public" class="session-list"> <div v-if="!$store.state.serverConfiguration.public" class="session-list">
<h2>Sessions</h2> <h2>Sessions</h2>
<h3>Current session</h3> <h3>Current session</h3>
<div v-if="$store.getters.currentSession" id="session-current"> <Session
<Session :session="$store.getters.currentSession" /> v-if="$store.getters.currentSession"
</div> :session="$store.getters.currentSession"
/>
<h3>Other sessions</h3> <h3>Other sessions</h3>
<div id="session-list"> <p v-if="$store.state.sessions.length === 0">Loading</p>
<p v-if="$store.state.sessions.length == 0">Loading</p> <p v-else-if="$store.getters.otherSessions.length === 0">
<p v-else-if="$store.getters.otherSessions.length == 0"> <em>You are not currently logged in to any other device.</em>
<em>You are not currently logged in to any other device.</em> </p>
</p> <Session
<template v-else> v-for="session in $store.getters.otherSessions"
<Session v-else
v-for="session in $store.getters.otherSessions" :key="session.token"
:key="session.token" :session="session"
:session="session" />
/>
</template>
</div>
</div> </div>
</form> </form>
</div> </div>

1189
client/css/bootstrap.css vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
@import "../../node_modules/normalize.css/normalize.css";
@import "fontawesome.css"; @import "fontawesome.css";
@import "bootstrap.css";
@import "../../node_modules/primer-tooltips/build/build.css"; @import "../../node_modules/primer-tooltips/build/build.css";
:root { :root {
@ -47,6 +47,43 @@
opacity: 1; /* fix opacity in Firefox */ opacity: 1; /* fix opacity in Firefox */
} }
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
input,
button,
select,
textarea {
font: inherit;
color: inherit;
}
img {
vertical-align: middle;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
abbr[title] {
cursor: help;
}
html, html,
body { body {
height: 100%; height: 100%;
@ -73,22 +110,17 @@ a,
a:hover, a:hover,
a:focus { a:focus {
color: var(--link-color); color: var(--link-color);
text-decoration: none;
} }
a:hover { a:hover {
text-decoration: underline; text-decoration: underline;
} }
/** a:focus {
* From Normalize. See https://github.com/thelounge/thelounge/pull/1217 outline: thin dotted;
* 1. Remove the bottom border in Chrome 57- and Firefox 39-. outline: 5px auto -webkit-focus-ring-color;
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. outline-offset: -2px;
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
} }
h1, h1,
@ -106,6 +138,7 @@ button {
outline: none; outline: none;
padding: 0; padding: 0;
user-select: inherit; user-select: inherit;
cursor: pointer;
} }
code, code,
@ -155,6 +188,10 @@ kbd {
box-shadow: 0 2px 0 #bbb, inset 0 1px 1px #fff, inset 0 -1px 3px #ccc; box-shadow: 0 2px 0 #bbb, inset 0 1px 1px #fff, inset 0 -1px 3px #ccc;
} }
p {
margin: 0 0 10px;
}
.btn { .btn {
border: 2px solid var(--button-color); border: 2px solid var(--button-color);
border-radius: 3px; border-radius: 3px;
@ -207,8 +244,10 @@ kbd {
} }
.container { .container {
padding: 0 15px;
margin-bottom: 20px; margin-bottom: 20px;
max-width: 480px; width: 480px;
align-self: center;
touch-action: pan-y; touch-action: pan-y;
} }
@ -247,7 +286,6 @@ kbd {
.channel-list-item::before, .channel-list-item::before,
#footer .icon, #footer .icon,
#chat .count::before, #chat .count::before,
#settings .extra-experimental,
#settings .extra-help, #settings .extra-help,
#settings #play::before, #settings #play::before,
#form #upload::before, #form #upload::before,
@ -357,12 +395,19 @@ kbd {
#help .documentation-link::before { content: "\f19d"; /* http://fontawesome.io/icon/graduation-cap/ */ } #help .documentation-link::before { content: "\f19d"; /* http://fontawesome.io/icon/graduation-cap/ */ }
#help .report-issue-link::before { content: "\f188"; /* http://fontawesome.io/icon/bug/ */ } #help .report-issue-link::before { content: "\f188"; /* http://fontawesome.io/icon/bug/ */ }
.session-list strong { .session-list .session-item {
display: block; display: flex;
font-size: 14px;
} }
.session-list p { .session-list .session-item-info {
margin-bottom: 10px; display: flex;
flex-direction: column;
flex-grow: 1;
}
.session-list .session-item-btn {
flex-shrink: 0;
} }
#chat .invite .from::before { #chat .invite .from::before {
@ -461,10 +506,6 @@ kbd {
line-height: 45px; line-height: 45px;
} }
#settings .extra-experimental::before {
content: "\f0c3"; /* https://fontawesome.com/icons/flask?style=solid */
}
#settings .extra-help::before { #settings .extra-help::before {
content: "\f059"; /* http://fontawesome.io/icon/question-circle/ */ content: "\f059"; /* http://fontawesome.io/icon/question-circle/ */
} }
@ -881,9 +922,10 @@ background on hover (unless active) */
border-color: #84ce88; border-color: #84ce88;
} }
#user-specified-css-input { textarea.input {
resize: vertical; resize: vertical;
height: 10em; height: 100px;
min-height: 35px;
padding: 6px 10px; padding: 6px 10px;
line-height: 1.5; line-height: 1.5;
} }
@ -924,7 +966,7 @@ background on hover (unless active) */
} }
.window h2 small { .window h2 small {
color: inherit; font-size: 16px;
line-height: 30px; line-height: 30px;
} }
@ -1110,7 +1152,6 @@ background on hover (unless active) */
padding-top: 15px; padding-top: 15px;
padding-bottom: 0; padding-bottom: 0;
width: 100%; width: 100%;
display: none;
} }
#chat .show-more .btn { #chat .show-more .btn {
@ -1205,10 +1246,6 @@ background on hover (unless active) */
padding: 0 10px; padding: 0 10px;
} }
#chat .unread-marker:last-child {
display: none;
}
#chat .date-marker { #chat .date-marker {
position: relative; position: relative;
text-align: center; text-align: center;
@ -1733,30 +1770,48 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */
width: 100%; width: 100%;
} }
#connect .connect-row {
display: flex;
}
#connect .connect-row > .input,
#connect .connect-row > .input-wrap {
flex-grow: 1;
}
#connect label { #connect label {
display: block; width: 25%;
flex-shrink: 0;
margin-top: 11px; margin-top: 11px;
} }
#connect .port::before {
content: ":";
margin: 9px 0 0 -17px;
position: absolute;
}
#connect .tls { #connect .tls {
float: left; width: 100%;
display: block;
margin-top: 6px; margin-top: 6px;
} }
#connect .tls input { #connect .tls input {
float: left;
margin: 3px 10px 0 0; margin: 3px 10px 0 0;
} }
#connect\:host {
width: 70%;
}
#connect\:port {
width: 25%;
}
#connect\:portseparator {
width: 5%;
text-align: center;
display: inline-block;
}
#connect .btn { #connect .btn {
float: left; margin-left: 25%;
margin-top: 30px; margin-top: 15px;
} }
#settings .settings-sync-panel { #settings .settings-sync-panel {
@ -1797,16 +1852,10 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */
margin-right: 6px; margin-right: 6px;
} }
#settings .extra-experimental {
color: #84ce88;
}
#settings .extra-experimental,
#settings .extra-help { #settings .extra-help {
cursor: help; cursor: help;
} }
#settings .extra-experimental,
#settings h2 .extra-help { #settings h2 .extra-help {
font-size: 0.8em; font-size: 0.8em;
} }
@ -1853,13 +1902,13 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */
#sign-in .password-container .reveal-password { #sign-in .password-container .reveal-password {
top: 31px; top: 31px;
right: 0;
} }
.password-container .reveal-password { .password-container .reveal-password {
position: absolute; position: absolute;
top: 2px; top: 2px;
right: 15px; right: 0;
appearance: none;
} }
.password-container .reveal-password span { .password-container .reveal-password span {
@ -1887,6 +1936,11 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */
color: #ff4136; color: #ff4136;
} }
#help .help-version-title {
display: flex;
justify-content: space-between;
}
#help .help-item { #help .help-item {
display: table-row; display: table-row;
font-size: 14px; font-size: 14px;
@ -2522,6 +2576,7 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */
@media (max-width: 479px) { @media (max-width: 479px) {
.container { .container {
max-width: 100%;
margin: 0; margin: 0;
} }
@ -2529,14 +2584,28 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */
width: 100%; width: 100%;
} }
#connect .tls {
margin: 20px 0;
}
.input { .input {
margin-bottom: 2px; margin-bottom: 2px;
} }
#connect .connect-row {
flex-direction: column;
}
#connect .connect-row > .input,
#connect .connect-row > .input-wrap {
flex-grow: 1;
}
#connect .btn {
margin-left: 0;
width: 100%;
}
#help .help-version-title {
flex-direction: column;
}
#chat .messages { #chat .messages {
display: block; display: block;
padding: 5px 0; padding: 5px 0;

View File

@ -96,6 +96,7 @@
"mocha": "6.2.2", "mocha": "6.2.2",
"mochapack": "1.1.13", "mochapack": "1.1.13",
"mousetrap": "1.6.3", "mousetrap": "1.6.3",
"normalize.css": "8.0.1",
"npm-run-all": "4.1.5", "npm-run-all": "4.1.5",
"nyc": "14.1.1", "nyc": "14.1.1",
"postcss-import": "12.0.1", "postcss-import": "12.0.1",

View File

@ -5835,6 +5835,11 @@ normalize-url@^4.1.0:
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
normalize.css@8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-8.0.1.tgz#9b98a208738b9cc2634caacbc42d131c97487bf3"
integrity sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==
npm-bundled@^1.0.1: npm-bundled@^1.0.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b"