UI: More compact layour, auto-scroll to user in shares

This commit is contained in:
Max Berger
2026-04-23 22:07:47 +02:00
parent ae6fee209a
commit c0a726ab8a
3 changed files with 160 additions and 43 deletions

View File

@@ -19,14 +19,17 @@ main {
.container {
height: auto;
min-height: 450px;
width: 350px;
min-height: 500px;
width: 95%;
max-width: 450px;
box-sizing: border-box;
transition: .2s;
overflow: hidden;
padding: 20px 40px;
background: #fff;
padding: 1ex 1em 1ex 1em;
background: rgb(250, 250, 250);
border: 1px solid #dadce0;
border-radius: 8px;
box-shadow: 2px 2px 3px #0000001a;
display: block;
flex-shrink: 0;
margin: 0 auto;
@@ -39,12 +42,55 @@ main {
color: #484848;
}
.container h2 {
margin: 0;
table {
width: 100%;
border-collapse: collapse;
margin: 1ex 0;
}
th,
td {
text-align: left;
color: #484848;
font-size: 14pt;
font-size: 0.8em;
padding: 0.2ex 0.2em;
}
tr {
border-bottom: 1px solid #dadce0;
}
tr:last-child {
border-bottom: none;
}
th {
font-size: 0.8em;
color: #666;
font-weight: normal;
text-transform: uppercase;
}
td.fill {
width: 100%;
}
details {
border: 1px solid #dadce0;
border-radius: 0.7ex;
padding: 0.5ex 0.7ex;
margin-bottom: 1ex;
background: white;
}
summary {
font-weight: bold;
cursor: pointer;
padding: 0.2ex 0;
outline: none;
}
summary:hover {
color: #2494fe;
}
#loginscene .infcloudlink {
@@ -394,6 +440,7 @@ select {
padding-left: 15px;
padding-right: 15px;
outline: none !important;
box-sizing: border-box;
}
input.inline {
@@ -402,7 +449,7 @@ input.inline {
input[type=text],
input[type=password] {
width: calc(100% - 30px);
width: 100%;
}
input:active,
@@ -421,13 +468,22 @@ input:focus-visible {
clear: both;
}
td .url-input-wrapper input {
min-height: 4ex;
}
.url-input-wrapper input {
flex: 1;
min-width: 0;
padding-right: 45px !important;
min-width: 40px;
min-height: 6ex;
padding-left: 0.5em;
padding-top: 0.5ex;
padding-bottom: 0.5ex;
padding-right: 22px !important;
box-sizing: border-box;
width: 100% !important;
margin-bottom: 0 !important;
height: 2ex;
}
#collectionsscene article .url-input-wrapper {
@@ -436,7 +492,7 @@ input:focus-visible {
.copy-btn {
flex: none;
margin-left: -38px;
margin-left: -30px;
background: transparent;
border: none;
color: #2494fe;
@@ -539,6 +595,9 @@ button.inline {
padding-right: 1px;
min-width: 2em;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
}
@media only screen and (max-width: 600px) {
@@ -547,22 +606,10 @@ button.inline {
flex-wrap: nowrap;
}
#collectionsscene article {
height: auto;
min-height: 375px;
}
.container {
max-width: 280px !important;
}
#collectionsscene ul {
visibility: visible !important;
}
#logoutview span {
padding: 0 5px;
}
}
.pill {
@@ -573,12 +620,12 @@ button.inline {
line-height: 1;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
border-radius: 0.375rem;
vertical-align: middle;
border-radius: 0.7ex;
background-color: #6c757d;
color: #fff;
margin: 0 2px;
width: 1.4em;
min-width: 1.3em;
}
.hidden {

View File

@@ -158,10 +158,11 @@
<tbody>
<tr data-name="sharetokenrowtemplate" class="hidden">
<td>
<button type="button" class="blue inline" data-name="edit" title="Edit Share"><img src="css/icons/edit.svg"
class="small_icon" alt="Edit"></button>
<button type="button" class="blue inline" data-name="edit" title="Edit Share"><img
src="css/icons/edit.svg" class="small_icon" alt="Edit"></button>
</td>
<td><span class="pill" data-name="rw">rw</span><span class="pill" data-name="ro">ro</span><span data-name="conversion"></span></td>
<td><span class="pill" data-name="rw">rw</span><span class="pill" data-name="ro">ro</span><span
data-name="conversion"></span></td>
<td>
<div class="url-input-wrapper">
<input type="text" data-name="pathortoken" value="" readonly="" class="inline selectall">
@@ -169,14 +170,17 @@
</div>
</td>
<td>
<button type="button" class="red inline" data-name="delete" title="Delete Share"><img src="css/icons/delete.svg"
class="small_icon" alt="Delete"></button>
<button type="button" class="red inline" data-name="delete" title="Delete Share"><img
src="css/icons/delete.svg" class="small_icon" alt="Delete"></button>
</td>
</tr>
<tr>
<td><button type="button" class="blue inline" data-name="sharebytoken" title="New Share by Token"><img src="css/icons/new.svg"
class="small_icon" alt="New Share by Token"></button>
<td><button type="button" class="blue inline" data-name="sharebytoken" title="New Share by Token"><img
src="css/icons/new.svg" class="small_icon" alt="New Share by Token"></button>
</td>
<td></td>
<td class="fill"></td>
<td></td>
</tr>
</tbody>
</table>
@@ -189,10 +193,11 @@
<tbody>
<tr data-name="sharemaprowtemplate" class="hidden">
<td>
<button type="button" class="blue inline" data-name="edit" title="Edit Share"><img src="css/icons/edit.svg"
class="small_icon" alt="Edit"></button>
<button type="button" class="blue inline" data-name="edit" title="Edit Share"><img
src="css/icons/edit.svg" class="small_icon" alt="Edit"></button>
</td>
<td><span class="pill" data-name="rw">rw</span><span class="pill" data-name="ro">ro</span><span data-name="conversion"></span></td>
<td><span class="pill" data-name="rw">rw</span><span class="pill" data-name="ro">ro</span><span
data-name="conversion"></span></td>
<td>
<div class="url-input-wrapper">
<input type="text" data-name="pathortoken" value="" readonly="" class="inline selectall">
@@ -200,8 +205,8 @@
</div>
</td>
<td>
<button type="button" class="red inline" data-name="delete" title="Delete Share"><img src="css/icons/delete.svg"
class="small_icon" alt="Delete"></button>
<button type="button" class="red inline" data-name="delete" title="Delete Share"><img
src="css/icons/delete.svg" class="small_icon" alt="Delete"></button>
</td>
</tr>
<tr>
@@ -210,6 +215,9 @@
<img src="css/icons/new.svg" class="small_icon" alt="New Share by Map">
</button>
</td>
<td></td>
<td class="fill"></td>
<td></td>
</tr>
</tbody>
</table>

View File

@@ -25,6 +25,9 @@ import { SERVER } from "../constants.js";
* Handles the display of URLs in input fields.
*/
export class UrlTextHandler {
/** @type {?HTMLCanvasElement} */
static _canvas = null;
/**
* @param {HTMLInputElement} element The input element to handle.
* @param {HTMLButtonElement} copyButton The button element for copying.
@@ -32,9 +35,14 @@ export class UrlTextHandler {
constructor(element, copyButton) {
this._element = element;
this._copyButton = copyButton;
this._userIndex = -1;
this._element.addEventListener("focusin", () => {
this._element.setSelectionRange(0, 99999);
this._updateScroll();
});
this._element.addEventListener("focusout", () => {
this._updateScroll();
});
if (this._copyButton) {
@@ -42,6 +50,37 @@ export class UrlTextHandler {
}
}
_updateScroll() {
setTimeout(() => {
this._updateScroll_now();
}, 0);
}
/**
* Update the scroll position of the input field.
*/
_updateScroll_now() {
if (this._userIndex === -1) {
this._element.scrollLeft = this._element.scrollWidth;
return;
}
let scrollPos = this._element.scrollWidth;
const value = this._element.value;
const style = window.getComputedStyle(this._element);
if (!UrlTextHandler._canvas) {
UrlTextHandler._canvas = document.createElement("canvas");
}
const context = UrlTextHandler._canvas.getContext("2d");
if (context) {
context.font = style.font;
const prefix = value.substring(0, this._userIndex);
scrollPos = context.measureText(prefix).width;
}
this._element.scrollLeft = scrollPos;
}
/**
* Copy the current value of the input to the clipboard.
*/
@@ -76,10 +115,33 @@ export class UrlTextHandler {
} else {
this._element.value = href;
}
this._update_username_index();
this._updateScroll();
}
// Needs timeout to work correctly.
setTimeout(() => {
this._element.scrollLeft = this._element.scrollWidth;
}, 0);
/**
* Update the username index.
*/
_update_username_index() {
const value = this._element.value;
this._userIndex = -1;
try {
const url = new URL(value);
const path = url.pathname;
const parts = path.split("/").filter(p => p !== "");
if (parts.length >= 2) {
const user = parts[parts.length - 2];
const search = "/" + user + "/";
const pathIndex = path.lastIndexOf(search);
if (pathIndex !== -1) {
const fullIndex = value.lastIndexOf(path);
if (fullIndex !== -1) {
this._userIndex = fullIndex + pathIndex;
}
}
}
} catch (e) {
this._userIndex = -1;
}
}
}