Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the WebShell dark mode toggle to be disabled #305

Merged
merged 8 commits into from
Feb 27, 2024
145 changes: 63 additions & 82 deletions src/main/resources/org/arl/fjage/web/shell/index.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
<!-- fjåge Web Shell

# API

- shellready : will be true when the shell is ready to accept input
- hideModeToggle : if true, the mode toggle button will be hidden
- window.postMessage({theme: 'dark'}) : to set the theme to 'dark' mode

-->
<html>
<head>
<title>fjåge shell</title>
Expand Down Expand Up @@ -36,88 +45,38 @@
right: 20px;
z-index: 100;
}
.tgl {
display: none;
}
.tgl, .tgl:after, .tgl:before, .tgl *, .tgl *:after, .tgl *:before, .tgl + .tgl-btn {
box-sizing: border-box;
}
.tgl::-moz-selection, .tgl:after::-moz-selection, .tgl:before::-moz-selection, .tgl *::-moz-selection, .tgl *:after::-moz-selection, .tgl *:before::-moz-selection, .tgl + .tgl-btn::-moz-selection {
background: none;
}
.tgl::selection, .tgl:after::selection, .tgl:before::selection, .tgl *::selection, .tgl *:after::selection, .tgl *:before::selection, .tgl + .tgl-btn::selection {
background: none;
}
.tgl + .tgl-btn {
outline: 0;
display: block;
width: 3.2em;
height: 1.5em;
position: relative;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.tgl + .tgl-btn:after, .tgl + .tgl-btn:before {
position: relative;
display: block;
content: "";
width: 40%;
height: 100%;
}
.tgl + .tgl-btn:after {
left: 0;
}
.tgl + .tgl-btn:before {
display: none;
}
.tgl:checked + .tgl-btn:after {
left: 60%;
}

.tgl-flat + .tgl-btn {
padding: 2px;
transition: all 0.2s ease;
background: #fff;
border: 4px solid #dfdfdf;
border-radius: 2em;
}
.tgl-flat + .tgl-btn:after {
transition: all 0.2s ease;
background: #dfdfdf;
content: "";
border-radius: 1em;
}
.tgl-flat:checked + .tgl-btn {
border: 4px solid #8d8d8d;
}
.tgl-flat:checked + .tgl-btn:after {
left: 60%;
background: #8d8d8d;
button.modeToggle {
background-color: transparent;
border: none;
cursor: pointer;
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div class="container">
<div id='terminal'></div>
<div class="btn-container" title="Toggle Light/Dark ColorMode">
<input class="tgl tgl-flat" id="darkmode-tgl" type="checkbox" checked/>
<label class="tgl-btn" for="darkmode-tgl"></label>
<button class="modeToggle" id="darkmode-tgl">
<svg id="darkmode-dark" style="display: none;" data-v-bd832875="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="icon" width="24px" height="24px" viewBox="0 0 24 24"><path fill="white" d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2h.1A6.98 6.98 0 0 0 10 7m-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938A7.999 7.999 0 0 0 4 12"></path></svg>
<svg id="darkmode-light" style="display: none;" data-v-bd832875="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="icon" width="24px" height="24px" viewBox="0 0 24 24"><path fill="currentColor" d="M12 18a6 6 0 1 1 0-12a6 6 0 0 1 0 12m0-2a4 4 0 1 0 0-8a4 4 0 0 0 0 8M11 1h2v3h-2zm0 19h2v3h-2zM3.515 4.929l1.414-1.414L7.05 5.636L5.636 7.05zM16.95 18.364l1.414-1.414l2.121 2.121l-1.414 1.414zm2.121-14.85l1.414 1.415l-2.121 2.121l-1.414-1.414zM5.636 16.95l1.414 1.414l-2.121 2.121l-1.414-1.414zM23 11v2h-3v-2zM4 11v2H1v-2z"></path></svg>
</button>
</div>
</div>
<script>
const ignoreKeys = ['Meta-R', 'Meta-Shift-R'];
var defaultCursorWidth;
var rtime = 0;
var resizing = false;
var delta = 200;
var fitAddon;
let defaultCursorWidth;
let rtime = 0;
let resizing = false;
let delta = 200;
let fitAddon;
let currentTheme = null;
window.shellready = false;
function connectSocket(term, url, path){
const ws = new WebSocket('ws://' + url + path);
var attachAddon;
let attachAddon;
window.ws = ws;
ws.onerror = () => reconnectSocket(term, attachAddon, url, path, ws)
ws.onclose = () => reconnectSocket(term, attachAddon, url, path, ws)
Expand Down Expand Up @@ -160,6 +119,9 @@
cursor: '#586e75',
selection: '#d3c494'
});
document.getElementById('darkmode-dark').style.display = 'none';
document.getElementById('darkmode-light').style.display = 'block';
currentTheme = theme;
}else if (theme == 'dark'){
term.setOption('theme', {
background: '#000000',
Expand All @@ -171,6 +133,9 @@
red: '#cc0000',
cursor: '#ff6e75'
});
document.getElementById('darkmode-dark').style.display = 'block';
document.getElementById('darkmode-light').style.display = 'none';
currentTheme = theme;
}
};
function resizeend() {
Expand All @@ -182,9 +147,17 @@
}
}
window.addEventListener('load', () => {
let hideModeToggle = false;
if (window.parent.document.documentElement.classList.contains('dark')){
currentTheme = 'dark';
hideModeToggle = true;
}else if (window.parent.document.documentElement.classList.contains('light')){
currentTheme = 'light';
hideModeToggle = true;
}
hideModeToggle = hideModeToggle || window.parent.hideModeToggle;
const darkmodeBtn = document.getElementById('darkmode-tgl');
var lightmode = false;
var userTheme = false;
let userTheme = false;

const term = new Terminal();
fitAddon = new FitAddon.FitAddon();
Expand All @@ -195,21 +168,29 @@
fitAddon.fit();
defaultCursorWidth = term.getOption("cursorWidth");

if (window.matchMedia){
lightmode = !window.matchMedia('(prefers-color-scheme: dark)').matches;
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
if (userTheme) return;
const newColorScheme = e.matches ? "dark" : "light";
darkmodeBtn.checked = !!e.matches;
setTheme(term, newColorScheme);
if (currentTheme == null && window.matchMedia) currentTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';

if (hideModeToggle){
darkmodeBtn.parentElement.style.display = 'none';
window.addEventListener('message', evt => {
if (evt.data && evt.data.theme){
setTheme(term, evt.data.theme);
}
});
}else {
if (window.matchMedia){
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
if (userTheme) return;
const newColorScheme = e.matches ? "dark" : "light";
setTheme(term, newColorScheme);
});
}
darkmodeBtn.addEventListener('click', evt => {
setTheme(term, currentTheme == 'dark' ? 'light' : 'dark');
userTheme = true;
})
}
darkmodeBtn.checked = !lightmode;
setTheme(term, lightmode ? 'light' : 'dark');
darkmodeBtn.addEventListener('change', evt => {
setTheme(term, evt.target.checked ? 'dark' : 'light');
userTheme = true;
})
setTheme(term, currentTheme);

const urlParams = new URLSearchParams(window.location.search);
const url = urlParams.get('url') || window.location.hostname + ':' + window.location.port;;
Expand Down
Loading