- dissolve core-bridge into api (wire contract), domain (models), services (what the UI calls) and worker (everything that runs in the Web Worker, grouped by account, crypto, space, files, shares, runtime); regroup features, lib and store by responsibility and delete unused components - the UI only reads backend capabilities (domain/capabilities); one tokenRole picks the token, hasCode/isRetryable handle errors; pre-checks that decided permissions on the client are gone; tests fail if those rules are reimplemented - files go straight to the file domain (create, upload, download, delete, commit, cancel); the host sees one registration per file; creating a channel allocates a file domain and works even when the file service is down - file panel shows which channel the files belong to and its space usage; unlimited files preview in chat; videos get a stored cover; the file service status is shown - fix: console flooded by Retry-After reads on every upload frame
188 lines
2.8 KiB
CSS
188 lines
2.8 KiB
CSS
.pane {
|
|
display: flex;
|
|
flex: 1;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
}
|
|
|
|
.head {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: var(--space-2);
|
|
min-height: var(--bar-h);
|
|
padding: 0 var(--space-4);
|
|
border-bottom: 1px solid var(--line);
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.scroll {
|
|
flex: 1;
|
|
min-height: 0;
|
|
padding: var(--space-2) var(--space-2) var(--space-4);
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.section h3 {
|
|
margin: var(--space-4) var(--space-2) var(--space-1);
|
|
color: var(--text-dim);
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.section ul {
|
|
margin: 0;
|
|
padding: 0;
|
|
list-style: none;
|
|
}
|
|
|
|
.row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-3);
|
|
min-height: 44px;
|
|
padding: var(--space-1) var(--space-2);
|
|
border-radius: var(--radius-md);
|
|
}
|
|
|
|
.row:hover,
|
|
.row:focus-within {
|
|
background: var(--accent-soft);
|
|
}
|
|
|
|
.avatar {
|
|
flex: 0 0 32px;
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: var(--radius-avatar);
|
|
object-fit: cover;
|
|
}
|
|
|
|
.avatarFallback {
|
|
display: grid;
|
|
place-items: center;
|
|
background: var(--surface-2);
|
|
color: var(--text-dim);
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.dim {
|
|
opacity: 0.6;
|
|
}
|
|
|
|
.who em {
|
|
margin-inline-start: var(--space-2);
|
|
padding: 0 var(--space-1);
|
|
border-radius: var(--radius-sm);
|
|
background: var(--surface-2);
|
|
color: var(--text-dim);
|
|
font-size: 11px;
|
|
font-style: normal;
|
|
font-weight: 400;
|
|
}
|
|
|
|
.who {
|
|
display: flex;
|
|
flex: 1;
|
|
flex-direction: column;
|
|
min-width: 0;
|
|
line-height: 1.3;
|
|
}
|
|
|
|
.who strong,
|
|
.who small {
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.who strong {
|
|
font-size: 14px;
|
|
}
|
|
|
|
.who small {
|
|
color: var(--text-dim);
|
|
font-size: 11px;
|
|
}
|
|
|
|
.online {
|
|
flex: 0 0 8px;
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: var(--radius-avatar);
|
|
background: var(--ok);
|
|
}
|
|
|
|
.remove {
|
|
opacity: 0;
|
|
}
|
|
|
|
.row:hover .remove,
|
|
.row:focus-within .remove {
|
|
opacity: 1;
|
|
}
|
|
|
|
@media (hover: none) {
|
|
.remove {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
.note,
|
|
.error {
|
|
margin: var(--space-4) var(--space-2) 0;
|
|
color: var(--text-dim);
|
|
font-size: 12px;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.error {
|
|
color: var(--danger);
|
|
}
|
|
|
|
.invite {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-3);
|
|
}
|
|
|
|
.invite label {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-2);
|
|
color: var(--text-dim);
|
|
font-size: 13px;
|
|
}
|
|
|
|
.invite input {
|
|
min-height: 42px;
|
|
padding: 0 var(--space-3);
|
|
border: 1px solid var(--line);
|
|
border-radius: var(--radius-md);
|
|
background: var(--surface-2);
|
|
color: var(--text);
|
|
font: inherit;
|
|
}
|
|
|
|
.invite .note {
|
|
margin: 0;
|
|
}
|
|
|
|
.inviteActions {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
.avatarButton {
|
|
display: block;
|
|
flex: none;
|
|
padding: 0;
|
|
border: 0;
|
|
border-radius: var(--radius-avatar);
|
|
background: none;
|
|
cursor: zoom-in;
|
|
}
|