WebSockets: transport surface implementation
This commit is contained in:
parent
33fdd023ab
commit
7118eff7eb
@ -49,7 +49,7 @@ ArdourGlobals::position_time () const
|
|||||||
bool
|
bool
|
||||||
ArdourGlobals::transport_roll () const
|
ArdourGlobals::transport_roll () const
|
||||||
{
|
{
|
||||||
return static_cast<bool>(basic_ui ().transport_rolling ());
|
return basic_ui ().transport_rolling ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -57,14 +57,14 @@ ArdourGlobals::set_transport_roll (bool value)
|
|||||||
{
|
{
|
||||||
if ((value && !transport_roll ()) || (!value && transport_roll ())) {
|
if ((value && !transport_roll ()) || (!value && transport_roll ())) {
|
||||||
// this call is equivalent to hitting the spacebar
|
// this call is equivalent to hitting the spacebar
|
||||||
basic_ui ().toggle_roll ();
|
basic_ui ().toggle_roll (false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ArdourGlobals::record_state () const
|
ArdourGlobals::record_state () const
|
||||||
{
|
{
|
||||||
return static_cast<bool>(session ().get_record_enabled ());
|
return session ().get_record_enabled ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
25
share/web_surfaces/builtin/transport/img/expand.svg
Normal file
25
share/web_surfaces/builtin/transport/img/expand.svg
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path fill="#FFFFFF" d="M28.939,34.766c-1.092-1.069-2.842-1.051-3.91,0.04L5.785,54.458V39.901c0-1.527-1.24-2.766-2.766-2.766
|
||||||
|
c-1.527,0-2.766,1.238-2.766,2.766v21.333c0,0.005,0.002,0.009,0.002,0.014c0,0.182,0.018,0.364,0.055,0.544
|
||||||
|
c0,0.006,0.004,0.012,0.004,0.019c0.037,0.169,0.088,0.336,0.156,0.497c0.027,0.069,0.07,0.13,0.104,0.195
|
||||||
|
c0.068,0.13,0.143,0.255,0.232,0.374c0.082,0.112,0.168,0.223,0.266,0.32c0.004,0.004,0.008,0.01,0.012,0.014
|
||||||
|
c0.053,0.052,0.115,0.091,0.172,0.138c0.078,0.065,0.152,0.134,0.236,0.19c0.082,0.053,0.168,0.092,0.252,0.136
|
||||||
|
c0.074,0.039,0.145,0.083,0.223,0.115c0.098,0.04,0.199,0.065,0.303,0.094c0.07,0.021,0.137,0.048,0.211,0.063
|
||||||
|
C2.658,63.98,2.838,64,3.02,64h21.332c1.527,0,2.766-1.238,2.766-2.766c0-1.526-1.238-2.766-2.766-2.766H9.598L28.98,38.676
|
||||||
|
C30.049,37.585,30.031,35.834,28.939,34.766z"/>
|
||||||
|
<path fill="#FFFFFF" d="M35.059,29.234c1.092,1.07,2.844,1.051,3.912-0.04L58.215,9.543v14.556c0,1.527,1.238,2.766,2.766,2.766
|
||||||
|
s2.766-1.238,2.766-2.766V2.766c0-0.005-0.002-0.009-0.002-0.014c0-0.182-0.018-0.363-0.055-0.543c0-0.007-0.004-0.014-0.006-0.02
|
||||||
|
c-0.035-0.17-0.086-0.336-0.154-0.498c-0.029-0.068-0.072-0.129-0.105-0.194c-0.066-0.13-0.141-0.255-0.23-0.374
|
||||||
|
c-0.082-0.112-0.168-0.223-0.268-0.32c-0.004-0.004-0.006-0.01-0.01-0.014c-0.055-0.053-0.117-0.091-0.172-0.138
|
||||||
|
c-0.078-0.065-0.152-0.134-0.238-0.19c-0.08-0.053-0.166-0.092-0.252-0.137c-0.072-0.038-0.145-0.082-0.221-0.114
|
||||||
|
c-0.1-0.04-0.201-0.065-0.303-0.095c-0.07-0.02-0.139-0.047-0.211-0.061C61.342,0.02,61.16,0,60.98,0H39.646
|
||||||
|
c-1.527,0-2.766,1.238-2.766,2.766s1.238,2.766,2.766,2.766H54.4L35.018,25.324C33.949,26.415,33.969,28.166,35.059,29.234z"/>
|
||||||
|
</g>
|
||||||
|
<rect fill="none" width="64" height="64"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
14
share/web_surfaces/builtin/transport/img/pause.svg
Normal file
14
share/web_surfaces/builtin/transport/img/pause.svg
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path fill="#FFFFFF" d="M27.7,3.078c0-1.295-1.049-2.345-2.345-2.345H10.503c-1.295,0-2.345,1.05-2.345,2.345v57.845
|
||||||
|
c0,1.294,1.05,2.345,2.345,2.345h14.852c1.294,0,2.345-1.051,2.345-2.345V3.078z"/>
|
||||||
|
<path fill="#FFFFFF" d="M55.842,3.078c0-1.295-1.051-2.345-2.346-2.345H38.645c-1.295,0-2.346,1.05-2.346,2.345v57.845
|
||||||
|
c0,1.294,1.051,2.345,2.346,2.345h14.852c1.295,0,2.346-1.051,2.346-2.345V3.078z"/>
|
||||||
|
</g>
|
||||||
|
<rect fill="none" width="64" height="64"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 857 B |
11
share/web_surfaces/builtin/transport/img/play.svg
Normal file
11
share/web_surfaces/builtin/transport/img/play.svg
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<path fill="#FFFFFF" d="M59.496,30.016v-0.022L6.908,0.422L6.902,0.426c-0.345-0.198-0.737-0.32-1.163-0.32
|
||||||
|
c-1.295,0-2.345,1.05-2.345,2.345V61.55c0,1.295,1.05,2.346,2.345,2.346c0.388,0,0.748-0.104,1.07-0.271l0.01,0.006L59.491,34.01
|
||||||
|
v-0.021c0.665-0.414,1.113-1.146,1.113-1.987C60.604,31.161,60.159,30.43,59.496,30.016z"/>
|
||||||
|
<rect fill="none" width="64" height="64"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 764 B |
10
share/web_surfaces/builtin/transport/img/record-off.svg
Normal file
10
share/web_surfaces/builtin/transport/img/record-off.svg
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<rect x="0" fill="none" width="64" height="64"/>
|
||||||
|
<path fill="#FFFFFF" d="M0.733,32c0,17.268,13.999,31.268,31.268,31.268l0,0c17.269,0,31.267-14,31.267-31.268l0,0
|
||||||
|
C63.268,14.73,49.27,0.732,32,0.732l0,0C14.732,0.732,0.733,14.73,0.733,32L0.733,32z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 646 B |
10
share/web_surfaces/builtin/transport/img/record-on.svg
Normal file
10
share/web_surfaces/builtin/transport/img/record-on.svg
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<rect x="0" fill="none" width="64" height="64"/>
|
||||||
|
<path fill="#EB392D" d="M0.733,32c0,17.268,13.999,31.268,31.268,31.268l0,0c17.269,0,31.267-14,31.267-31.268l0,0
|
||||||
|
C63.268,14.73,49.27,0.732,32,0.732l0,0C14.732,0.732,0.733,14.73,0.733,32L0.733,32z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 646 B |
@ -3,8 +3,20 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Ardour Transport</title>
|
<title>Ardour Transport</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" type="text/css" href="main.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Under Construction</h1>
|
<div id="main">
|
||||||
|
<div id="ui">
|
||||||
|
<div id="time"></div>
|
||||||
|
<div id="buttons">
|
||||||
|
<button id="roll"></button>
|
||||||
|
<button id="record"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button id="fullscreen"></button>
|
||||||
|
<script type="module" src="main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
97
share/web_surfaces/builtin/transport/main.css
Normal file
97
share/web_surfaces/builtin/transport/main.css
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
background: #000;
|
||||||
|
color: rgb(248,248,242);
|
||||||
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
position: fixed;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background: rgb(62,61,61);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ui {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 768px;
|
||||||
|
height: 384px;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
background: rgba(0,0,0,0.1);
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: default;
|
||||||
|
user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#time {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 320px) {
|
||||||
|
#time {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#buttons {
|
||||||
|
display: flex;
|
||||||
|
flex: 2;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#buttons > button {
|
||||||
|
height: 148px;
|
||||||
|
width: 148px;
|
||||||
|
max-height: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
border: solid 16px transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fullscreen {
|
||||||
|
position: fixed;
|
||||||
|
top: 16px;
|
||||||
|
right: 12px;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
opacity: 0.5;
|
||||||
|
background-image: url('img/expand.svg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.pulse {
|
||||||
|
animation: pulse 1s infinite ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
135
share/web_surfaces/builtin/transport/main.js
Normal file
135
share/web_surfaces/builtin/transport/main.js
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Luciano Iam <lucianito@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ArdourClient } from '/shared/ardour.js';
|
||||||
|
|
||||||
|
(() => {
|
||||||
|
|
||||||
|
const dom = {
|
||||||
|
main: document.getElementById('main'),
|
||||||
|
time: document.getElementById('time'),
|
||||||
|
roll: document.getElementById('roll'),
|
||||||
|
record: document.getElementById('record'),
|
||||||
|
fullscreen: document.getElementById('fullscreen')
|
||||||
|
};
|
||||||
|
|
||||||
|
const ardour = new ArdourClient(location.host);
|
||||||
|
|
||||||
|
let _rolling = false;
|
||||||
|
let _record = false;
|
||||||
|
|
||||||
|
function main () {
|
||||||
|
addDomEventListeners ();
|
||||||
|
|
||||||
|
ardour.addCallbacks({
|
||||||
|
onError: console.log,
|
||||||
|
onPositionTime: setPosition,
|
||||||
|
onTransportRoll: setRolling,
|
||||||
|
onRecordState: setRecord
|
||||||
|
});
|
||||||
|
|
||||||
|
ardour.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
function addDomEventListeners () {
|
||||||
|
// transport buttons
|
||||||
|
const touchOrClick = ('ontouchstart' in document.documentElement) ? 'touchstart' : 'click';
|
||||||
|
|
||||||
|
const roll = () => {
|
||||||
|
setRolling (!_rolling);
|
||||||
|
ardour.setTransportRoll (_rolling);
|
||||||
|
};
|
||||||
|
|
||||||
|
dom.roll.addEventListener(touchOrClick, roll);
|
||||||
|
|
||||||
|
const record = () => {
|
||||||
|
setRecord (!_record);
|
||||||
|
ardour.setRecordState (_record);
|
||||||
|
};
|
||||||
|
|
||||||
|
dom.record.addEventListener(touchOrClick, record);
|
||||||
|
|
||||||
|
// fullscreen button
|
||||||
|
let requestFullscreen = null, fullscreenChange = null;
|
||||||
|
|
||||||
|
if ('requestFullscreen' in dom.main) {
|
||||||
|
requestFullscreen = dom.main.requestFullscreen.bind(dom.main);
|
||||||
|
fullscreenChange = 'fullscreenchange';
|
||||||
|
} else if ('webkitRequestFullscreen' in dom.main) {
|
||||||
|
requestFullscreen = dom.main.webkitRequestFullscreen.bind(dom.main);
|
||||||
|
fullscreenChange = 'webkitfullscreenchange';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestFullscreen && fullscreenChange) {
|
||||||
|
dom.fullscreen.addEventListener(touchOrClick, requestFullscreen);
|
||||||
|
|
||||||
|
document.addEventListener(fullscreenChange, (e) => {
|
||||||
|
const fullscreen = document.fullScreen || document.webkitIsFullScreen;
|
||||||
|
dom.fullscreen.style.display = fullscreen ? 'none' : 'inline';
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
dom.fullscreen.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
// keyboard actions
|
||||||
|
document.addEventListener('keydown', (e) => {
|
||||||
|
const key = e.key.toLowerCase();
|
||||||
|
|
||||||
|
if (key == ' ') {
|
||||||
|
roll();
|
||||||
|
} else if (key == 'r') {
|
||||||
|
record();
|
||||||
|
} else if (key == 'f') {
|
||||||
|
requestFullscreen();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPosition (seconds) {
|
||||||
|
const h = Math.floor(seconds / 3600),
|
||||||
|
m = Math.floor((seconds - 3600 * h) / 60),
|
||||||
|
s = Math.floor(seconds - 3600 * h - 60 * m),
|
||||||
|
ms = Math.round(1000 * (seconds % 1)),
|
||||||
|
time = (h < 10 ? '0' + h : h)
|
||||||
|
+ ':' + (m < 10 ? '0' + m : m)
|
||||||
|
+ ':' + (s < 10 ? '0' + s : s)
|
||||||
|
+ '.' + (ms < 100 ? (ms < 10 ? '00' + ms : '0' + ms) : ms);
|
||||||
|
dom.time.innerHTML = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setRolling (rolling) {
|
||||||
|
_rolling = rolling
|
||||||
|
const image = _rolling ? 'img/pause.svg' : 'img/play.svg';
|
||||||
|
dom.roll.style.backgroundImage = `url(${image})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setRecord (record) {
|
||||||
|
_record = record;
|
||||||
|
|
||||||
|
if (_record) {
|
||||||
|
dom.record.style.backgroundImage = 'url(img/record-on.svg)';
|
||||||
|
dom.record.classList.add('pulse');
|
||||||
|
} else {
|
||||||
|
dom.record.style.backgroundImage = 'url(img/record-off.svg)';
|
||||||
|
dom.record.classList.remove('pulse');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
||||||
|
})();
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<WebSurface>
|
<WebSurface>
|
||||||
<Name value="Transport"/>
|
<Name value="Transport"/>
|
||||||
<Description value="Provides basic transport control (under construction)"/>
|
<Description value="Provides basic transport control"/>
|
||||||
<Version value="0.1.0"/>
|
<Version value="0.1.0"/>
|
||||||
</WebSurface>
|
</WebSurface>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Ardour Web Surfaces</title>
|
<title>Ardour Web Surfaces</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" type="text/css" href="index/main.css">
|
<link rel="stylesheet" type="text/css" href="index/main.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -76,6 +76,12 @@ h2 {
|
|||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 320px) {
|
||||||
|
.surface-list > ul {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.surface-list > ul > li {
|
.surface-list > ul > li {
|
||||||
margin: 4ex 0;
|
margin: 4ex 0;
|
||||||
}
|
}
|
||||||
@ -89,4 +95,5 @@ h2 {
|
|||||||
font-family: Monaco, monospace;
|
font-family: Monaco, monospace;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
color: #444;
|
color: #444;
|
||||||
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user