Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b86b69d171 | |||
| e009496885 | |||
| 690692b494 | |||
| 5df8bdf932 | |||
| 030966c506 | |||
| 5a633a0ebb | |||
| 50d03aad1d | |||
| 29b754c9f8 | |||
| 9c90ede9c4 | |||
| 35bdc7473f | |||
| 3255e2ec29 | |||
| a550178de7 | |||
| 18284ef0f2 | |||
| a6b30c1b19 | |||
| 4a41e3f114 | |||
| 106bece811 | |||
| ad022b9472 | |||
| da2f07783d | |||
| d11fd87696 | |||
| 7cf278beb1 | |||
| ab2b2c940a | |||
| 3ca9c00725 | |||
| edd095efc4 | |||
| 5832cd0449 | |||
| d821417a3f | |||
| 8a2bfff1d9 | |||
| e6c548611b | |||
| 47b834779a | |||
| eb0a7d4522 | |||
| 61ce605627 | |||
| cda2271e9e | |||
| ef43b377c1 | |||
| 5605404bae | |||
| 211b14db78 | |||
| 160ddead30 | |||
| 2a3f7f2dec | |||
| 52dbfeadda | |||
| 876b4c742c | |||
| 12040df452 | |||
| 80c28bc155 | |||
| dbae95dca4 | |||
| 45681069cd | |||
| de7992d60c | |||
| 88a7eb03a7 | |||
| 3474e341a5 | |||
| 8e82c4687e | |||
| e8fcc3d2b9 | |||
| 2b44055047 | |||
| f8c30eabde | |||
| 3e521505c0 | |||
| 442ed2f1d1 | |||
| 26020e3e95 | |||
| 28d77a898c | |||
| 5b4b57306b | |||
| 2e4ce08874 | |||
| b49724d83b |
@@ -1,9 +1,7 @@
|
|||||||
name: Build and Push Matrix-to Docker Image
|
name: Build and Push Matrix-to Docker Image
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
workflow_dispatch: # Erlaubt den manuellen Start über das GitHub UI
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -25,5 +23,7 @@ jobs:
|
|||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v2
|
||||||
with:
|
with:
|
||||||
|
context: .
|
||||||
push: true
|
push: true
|
||||||
tags: domoel/matrix-to:latest
|
tags: domoel/matrix-to:latest
|
||||||
|
no-cache: true
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ The matrix.to URL scheme is
|
|||||||
The #/ component is mandatory and exists to avoid leaking the target URL to the
|
The #/ component is mandatory and exists to avoid leaking the target URL to the
|
||||||
server hosting matrix.to.
|
server hosting matrix.to.
|
||||||
|
|
||||||
|
There is no _Entity type_ for **Spaces**, as they are technically just rooms.
|
||||||
|
|
||||||
Note that linking to rooms by ID should only be used for rooms to which the
|
Note that linking to rooms by ID should only be used for rooms to which the
|
||||||
target user has been invited: these links cannot be assumed to work for all
|
target user has been invited: these links cannot be assumed to work for all
|
||||||
visitors.
|
visitors.
|
||||||
|
|||||||
+106
-71
@@ -1,98 +1,133 @@
|
|||||||
.ClientListView h2 {
|
.ClientListView h2 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 18px 0;
|
margin: 24px 0;
|
||||||
}
|
font-weight: 600;
|
||||||
|
|
||||||
.ClientListView .filterOption {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin: 8px 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ClientView {
|
.ClientView {
|
||||||
border: 1px solid #E6E6E6;
|
background: var(--app-background);
|
||||||
border-radius: 8px;
|
border: 1px solid var(--borders);
|
||||||
|
border-radius: 4px;
|
||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
padding: 16px;
|
padding: 24px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-left: 4px solid transparent;
|
||||||
|
display: block;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ClientView:hover {
|
||||||
|
background: #2f313d !important;
|
||||||
|
border-left-color: var(--ztfr-purple) !important;
|
||||||
|
transform: translateX(5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ClientView.isPreferred {
|
.ClientView.isPreferred {
|
||||||
border: 3px solid var(--link);
|
border-color: var(--ztfr-purple);
|
||||||
box-shadow: 0px 8px 4px rgba(0, 0, 0, 0.05);
|
background: rgba(189, 147, 249, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ClientView .hostedBanner {
|
.ClientView .hostedBanner {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 29px;
|
margin-bottom: 20px;
|
||||||
padding: 4px 0;
|
padding: 6px 0;
|
||||||
line-height: 20px;
|
border-radius: 4px;
|
||||||
border-radius: 8px;
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 16px;
|
font-size: 13px;
|
||||||
background-color: var(--lightgrey);
|
background-color: var(--ztfr-purple);
|
||||||
|
color: var(--app-background);
|
||||||
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ClientView .header {
|
.ClientView .header { display: flex; align-items: flex-start; }
|
||||||
display: flex;
|
.ClientView .description { flex: 1; }
|
||||||
}
|
.ClientView h3 { margin: 0 0 8px 0; font-size: 18px; }
|
||||||
|
.ClientView .description p { margin: 0; font-size: 13px; color: var(--font); }
|
||||||
.ClientView .description {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ClientView h3 {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ClientView .clientIcon {
|
.ClientView .clientIcon {
|
||||||
border-radius: 8px;
|
border-radius: 4px;
|
||||||
background-repeat: no-repeat;
|
background-color: #ffffff;
|
||||||
background-size: cover;
|
padding: 4px;
|
||||||
width: 60px;
|
width: 50px;
|
||||||
height: 60px;
|
height: 50px;
|
||||||
overflow: hidden;
|
|
||||||
display: block;
|
|
||||||
margin-left: 16px;
|
margin-left: 16px;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ClientView .platforms {
|
.ClientView .platforms {
|
||||||
background-image: url('../images/platform-icon.svg');
|
margin-top: 12px;
|
||||||
background-repeat: no-repeat;
|
font-size: 12px;
|
||||||
background-position: 0 center;
|
color: var(--grey);
|
||||||
padding-left: 28px;
|
opacity: 0.8;
|
||||||
}
|
|
||||||
|
|
||||||
.ClientView .actions a.badge {
|
|
||||||
display: inline-block;
|
|
||||||
height: 40px;
|
|
||||||
margin: 8px 16px 8px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ClientView .actions img {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ClientView .back {
|
|
||||||
margin-top: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.InstallClientView .instructions button {
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: center;
|
|
||||||
background-color: transparent;
|
|
||||||
padding: 4px;
|
|
||||||
border: none;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
margin: 8px;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.InstallClientView .instructions button.copy {
|
|
||||||
background-image: url('../images/copy.svg');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.InstallClientView .instructions button.tick {
|
.InstallClientView .instructions button.tick {
|
||||||
background-image: url('../images/tick-dark.svg');
|
filter: invert(1); /* Macht schwarze Icons weiß */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ClientView .back {
|
||||||
|
display: block;
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ClientView .actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ClientView .actions a.badge {
|
||||||
|
height: auto !important;
|
||||||
|
max-width: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ClientView .actions img {
|
||||||
|
max-width: 160px;
|
||||||
|
height: auto;
|
||||||
|
display: block;
|
||||||
|
margin: 5px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- ANPASSUNG FÜR DEN DEZENTEN LOOK --- */
|
||||||
|
|
||||||
|
.ClientView .actions .footer {
|
||||||
|
display: block !important; /* Kein Flex mehr, damit Links wie Text fließen */
|
||||||
|
text-align: center !important;
|
||||||
|
margin-top: 20px !important;
|
||||||
|
width: 100%;
|
||||||
|
line-height: 1.8 !important; /* Gibt den Zeilen etwas Platz */
|
||||||
|
color: var(--sub-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Der "Use Custom Web Instance" Bereich bekommt eine eigene Zeile */
|
||||||
|
.ClientView .actions .footer .custom {
|
||||||
|
display: block !important;
|
||||||
|
margin-top: 6px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sicherstellen, dass der "Change" Button im Textfluss bleibt */
|
||||||
|
.ClientView .actions .footer button.change {
|
||||||
|
display: inline !important;
|
||||||
|
margin: 0 4px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 480px) {
|
||||||
|
.ClientView {
|
||||||
|
padding: 15px;
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ClientView .header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ClientView .clientIcon {
|
||||||
|
margin: 0 0 15px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+168
-157
@@ -1,17 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
Modified 2026 for Zeitfresser Matrix Community Look & Mobile Fixes
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import url('spinner.css');
|
@import url('spinner.css');
|
||||||
@@ -20,57 +9,63 @@ limitations under the License.
|
|||||||
@import url('create.css');
|
@import url('create.css');
|
||||||
@import url('open.css');
|
@import url('open.css');
|
||||||
|
|
||||||
|
/* Globaler Fix für Box-Berechnungen */
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--app-background: #f4f4f4;
|
--app-background: #1e1f29; /* Tief-Anthrazit */
|
||||||
--background: #ffffff;
|
--background: #282a36; /* Card Hintergrund */
|
||||||
--foreground: #000000;
|
--foreground: #f7f7fa; /* Weiß */
|
||||||
--font: #333333;
|
--font: #bdc3c7; /* Grau */
|
||||||
--grey: #666666;
|
--grey: #64748b; /* Dunkles Grau */
|
||||||
--accent: #0098d4;
|
--accent: #0dbd8b; /* Matrix-Green */
|
||||||
--error: #d6001c;
|
--ztfr-purple: #bd93f9; /* Zeitfresser-Lila */
|
||||||
--link: #0098d4;
|
--error: #ff5555;
|
||||||
--borders: #f4f4f4;
|
--link: #f7f7fa;
|
||||||
--lightgrey: #E6E6E6;
|
--borders: #2f313d;
|
||||||
|
--lightgrey: #383a59;
|
||||||
--spinner-stroke-size: 2px;
|
--spinner-stroke-size: 2px;
|
||||||
|
--sub-text: #bdc3c7;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: var(--app-background);
|
background-color: var(--app-background);
|
||||||
background-image: url('../images/background.svg');
|
background-image: none !important;
|
||||||
background-attachment: fixed;
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: auto;
|
|
||||||
background-position: center -50px;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 14px;
|
|
||||||
color: var(--font);
|
color: var(--font);
|
||||||
padding: 120px 0 0 0;
|
padding: 80px 20px 0 20px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
noscript {
|
h1, h2, h3 {
|
||||||
display: block;
|
color: var(--foreground);
|
||||||
padding: 20px;
|
letter-spacing: -0.5px;
|
||||||
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
p { line-height: 150%; }
|
p {
|
||||||
a { text-decoration: none; }
|
line-height: 1.7;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
h1 { font-size: 24px; }
|
a { text-decoration: none; color: var(--link); }
|
||||||
h2 { font-size: 21px; }
|
|
||||||
h3 { font-size: 16px; }
|
|
||||||
|
|
||||||
body,
|
body, button, input, textarea {
|
||||||
button,
|
font-size: 14px;
|
||||||
input,
|
|
||||||
textarea {
|
|
||||||
font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
|
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,13 +73,14 @@ button, input[type=submit] {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
button, input {
|
/* Die zentrale Kachel */
|
||||||
font-size: inherit;
|
.card {
|
||||||
font-weight: inherit;
|
background-color: var(--background);
|
||||||
}
|
border-radius: 4px;
|
||||||
|
border-left: 4px solid var(--ztfr-purple);
|
||||||
input[type="checkbox"], input[type="radio"] {
|
box-shadow: 0px 20px 40px rgba(0, 0, 0, 0.3);
|
||||||
margin: 0 8px 0 0;
|
padding: 2.5rem;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.RootView {
|
.RootView {
|
||||||
@@ -93,131 +89,146 @@ input[type="checkbox"], input[type="radio"] {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
/* --- GROSSE BUTTONS (z.B. Download, Continue) --- */
|
||||||
background-color: var(--background);
|
|
||||||
border-radius: 16px;
|
|
||||||
box-shadow: 0px 18px 24px rgba(0, 0, 0, 0.06);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card, .footer {
|
|
||||||
padding: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hidden {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@media screen and (max-width: 480px) {
|
|
||||||
body {
|
|
||||||
background-image: none;
|
|
||||||
background-color: var(--background);
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
border-radius: unset;
|
|
||||||
box-shadow: unset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer .links li:not(:first-child) {
|
|
||||||
margin-left: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer .links li:not(:first-child)::before {
|
|
||||||
content: "·";
|
|
||||||
margin-right: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer .links li {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer .links {
|
|
||||||
font-size: 12px;
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a, button.text {
|
|
||||||
color: var(--link);
|
|
||||||
}
|
|
||||||
|
|
||||||
button.text {
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: inherit;
|
|
||||||
padding: 8px 0;
|
|
||||||
margin: -8px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.text:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.primary, .secondary {
|
.primary, .secondary {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 12px 8px;
|
padding: 14px 20px;
|
||||||
margin: 8px 0;
|
margin: 4px 0 !important;
|
||||||
}
|
display: block;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
.secondary {
|
/* Simplifizierung: Nur Farbe, keine Bewegung */
|
||||||
background: var(--background);
|
transition: background-color 0.2s ease, filter 0.2s ease;
|
||||||
color: var(--link);
|
transform: none !important;
|
||||||
border: 1px solid var(--link);
|
-webkit-font-smoothing: antialiased;
|
||||||
border-radius: 32px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.primary {
|
.primary {
|
||||||
background: var(--link);
|
background: var(--foreground);
|
||||||
color: var(--background);
|
color: var(--app-background) !important;
|
||||||
border-radius: 32px;
|
border-radius: 4px;
|
||||||
}
|
|
||||||
|
|
||||||
.primary.icon, .secondary.icon {
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: 12px center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon.link { background-image: url('../images/link.svg'); }
|
|
||||||
.icon.tick { background-image: url('../images/tick.svg'); }
|
|
||||||
.icon.copy { background-image: url('../images/copy.svg'); }
|
|
||||||
|
|
||||||
button.primary, input[type='submit'].primary, button.secondary, input[type='submit'].secondary {
|
|
||||||
border: none;
|
border: none;
|
||||||
font-size: inherit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.primary:hover {
|
||||||
|
filter: brightness(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondary {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--foreground);
|
||||||
|
border: 1px solid var(--foreground);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondary:hover {
|
||||||
|
background: rgba(255,255,255,0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- DEZENTE BUTTONS (Change, Custom Instance, Footer-Style) --- */
|
||||||
|
.ClientListView button.change,
|
||||||
|
.PreviewView button.change,
|
||||||
|
.ClientView button.custom,
|
||||||
|
.ClientView .footer button,
|
||||||
|
.CustomInstanceView .actions button.secondary,
|
||||||
|
.footer button,
|
||||||
|
.footer a {
|
||||||
|
background: none !important;
|
||||||
|
border: none !important;
|
||||||
|
color: var(--grey) !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
font-family: inherit !important;
|
||||||
|
font-size: inherit !important;
|
||||||
|
font-weight: normal !important;
|
||||||
|
text-transform: none !important;
|
||||||
|
letter-spacing: normal !important;
|
||||||
|
cursor: pointer !important;
|
||||||
|
display: inline !important;
|
||||||
|
width: auto !important;
|
||||||
|
border-bottom: 1px solid rgba(189, 195, 199, 0.3) !important;
|
||||||
|
transition: all 0.3s ease !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ClientListView button.change:hover,
|
||||||
|
.PreviewView button.change:hover,
|
||||||
|
.ClientView button.custom:hover,
|
||||||
|
.ClientView .footer button:hover,
|
||||||
|
.CustomInstanceView .actions button.secondary:hover,
|
||||||
|
.footer button:hover,
|
||||||
|
.footer a:hover {
|
||||||
|
color: var(--foreground) !important;
|
||||||
|
border-bottom-color: var(--ztfr-purple) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fix für Button-Container */
|
||||||
|
.actions,
|
||||||
|
.ClientView .actions,
|
||||||
|
.ClientListView .actions,
|
||||||
|
.CustomInstanceView .actions {
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: column !important;
|
||||||
|
gap: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions > *:last-child {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Input Felder */
|
||||||
input[type='text'].large {
|
input[type='text'].large {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 12px;
|
padding: 14px;
|
||||||
background: var(--background);
|
background: #1a1a1a !important;
|
||||||
border: 1px solid var(--foreground);
|
border: 1px solid var(--borders);
|
||||||
border-radius: 16px;
|
border-radius: 4px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
color: var(--foreground);
|
||||||
|
|
||||||
.fullwidth {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.LoadServerPolicyView {
|
.footer {
|
||||||
display: flex;
|
margin-top: 60px;
|
||||||
|
padding: 40px 20px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--sub-text);
|
||||||
|
opacity: 0.7;
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.05);
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.LoadServerPolicyView .spinner {
|
.footer ul { list-style: none; padding: 0; margin: 0; }
|
||||||
width: 32px;
|
.footer li { display: inline; margin: 0; }
|
||||||
height: 32px;
|
|
||||||
margin-right: 12px;
|
@media screen and (max-width: 480px) {
|
||||||
|
body { padding: 40px 10px 0 10px; }
|
||||||
|
.card { padding: 1.5rem; border-radius: 2px; }
|
||||||
|
h1 { font-size: 1.5rem; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.LoadServerPolicyView h2 {
|
/* --- FIX FÜR NUTZERPROFILE (null-Werte verstecken) --- */
|
||||||
margin-top: 0;
|
|
||||||
|
.PreviewView .members[data-count="null"],
|
||||||
|
.PreviewView .members:empty {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PreviewView .topic:empty,
|
||||||
|
.PreviewView .topic:contains("null") {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PreviewView p:empty,
|
||||||
|
.PreviewView span:empty {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PreviewView h2 + p {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-89
@@ -4,130 +4,95 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.PreviewView h1 {
|
.PreviewView h1 {
|
||||||
font-size: 24px;
|
font-size: 26px;
|
||||||
line-height: 32px;
|
line-height: 1.2;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
word-wrap: anywhere;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.PreviewView .avatarContainer {
|
.PreviewView .avatarContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin: 0;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.PreviewView .avatar {
|
.PreviewView .avatar {
|
||||||
border-radius: 100%;
|
border-radius: 8px; /* Eckig */
|
||||||
width: 64px;
|
width: 80px;
|
||||||
height: 64px;
|
height: 80px;
|
||||||
}
|
border: 3px solid var(--borders);
|
||||||
|
object-fit: cover;
|
||||||
.PreviewView .mxSpace .avatar {
|
|
||||||
border-radius: 12px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.PreviewView .defaultAvatar {
|
.PreviewView .defaultAvatar {
|
||||||
width: 64px;
|
width: 80px;
|
||||||
height: 64px;
|
height: 80px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: var(--lightgrey);
|
||||||
background-image: url('../images/chat-icon.svg');
|
background-image: url('../images/chat-icon.svg');
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-size: 85%;
|
opacity: 0.6;
|
||||||
}
|
|
||||||
|
|
||||||
.PreviewView .spinner {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.PreviewView .avatar.loading {
|
|
||||||
border: 1px solid #eee;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.PreviewView .identifier {
|
.PreviewView .identifier {
|
||||||
color: var(--grey);
|
color: var(--ztfr-purple);
|
||||||
font-size: 12px;
|
font-family: monospace;
|
||||||
|
font-size: 13px;
|
||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
}
|
letter-spacing: 0.5px;
|
||||||
|
|
||||||
.PreviewView .identifier.placeholder {
|
|
||||||
height: 1em;
|
|
||||||
margin: 1em 30%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.PreviewView .memberCount {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
margin: 8px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.PreviewView .memberCount.loading {
|
|
||||||
margin: 16px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.PreviewView .memberCount p {
|
|
||||||
font-size: 12px;
|
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.PreviewView .memberCount p:not(.placeholder) {
|
.PreviewView .memberCount p:not(.placeholder) {
|
||||||
padding: 4px 8px 4px 24px;
|
padding: 6px 12px 6px 28px;
|
||||||
border-radius: 14px;
|
border-radius: 4px;
|
||||||
|
color: var(--foreground);
|
||||||
background-image: url(../images/member-icon.svg);
|
background-image: url(../images/member-icon.svg);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: 2px center;
|
background-position: 8px center;
|
||||||
background-color: var(--lightgrey);
|
background-color: var(--lightgrey);
|
||||||
}
|
display: inline-block;
|
||||||
|
font-size: 12px;
|
||||||
.PreviewView .memberCount p.placeholder {
|
|
||||||
height: 1.5em;
|
|
||||||
width: 100px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.PreviewView .topic {
|
.PreviewView .topic {
|
||||||
font-size: 12px;
|
font-size: 14px;
|
||||||
color: var(--grey);
|
line-height: 1.6;
|
||||||
margin: 32px 0;
|
color: var(--font);
|
||||||
}
|
margin: 24px 0;
|
||||||
|
|
||||||
.PreviewView .topic.loading {
|
|
||||||
display: block;
|
|
||||||
margin: 24px 12px;
|
|
||||||
padding: 4px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.PreviewView .topic.loading .placeholder {
|
|
||||||
height: 0.8em;
|
|
||||||
display: block;
|
|
||||||
margin: 12px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.PreviewView .topic.loading .placeholder:nth-child(2) {
|
|
||||||
margin-left: 5%;
|
|
||||||
margin-right: 5%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dark Mode Placeholders */
|
||||||
.placeholder {
|
.placeholder {
|
||||||
border-radius: 1em;
|
border-radius: 4px;
|
||||||
--flash-bg: #ddd;
|
--flash-bg: #2f313d;
|
||||||
--flash-fg: #eee;
|
--flash-fg: #383a59;
|
||||||
background: linear-gradient(120deg,
|
background: linear-gradient(120deg, var(--flash-bg), var(--flash-bg) 10%, var(--flash-fg) calc(10% + 25px), var(--flash-bg) calc(10% + 50px));
|
||||||
var(--flash-bg),
|
|
||||||
var(--flash-bg) 10%,
|
|
||||||
var(--flash-fg) calc(10% + 25px),
|
|
||||||
var(--flash-bg) calc(10% + 50px)
|
|
||||||
);
|
|
||||||
animation: flash 2s linear infinite;
|
animation: flash 2s linear infinite;
|
||||||
background-size: 200%;
|
background-size: 200%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes flash {
|
@keyframes flash {
|
||||||
0% { background-position-x: 0; }
|
0% { background-position-x: 0; }
|
||||||
50% { background-position-x: -80%; }
|
100% { background-position-x: -200%; }
|
||||||
51% { background-position-x: 80%; }
|
}
|
||||||
100% { background-position-x: 0%; }
|
|
||||||
|
.PreviewView h1,
|
||||||
|
.PreviewView .identifier,
|
||||||
|
.PreviewView .topic {
|
||||||
|
word-wrap: break-word; /* Bricht extrem lange Wörter/IDs um */
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 480px) {
|
||||||
|
.PreviewView .avatar,
|
||||||
|
.PreviewView .defaultAvatar {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PreviewView h1 {
|
||||||
|
font-size: 20px; /* Titel etwas dezenter mobil */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-3
@@ -18,7 +18,7 @@ import {createEnum} from "./utils/enum.js";
|
|||||||
import {orderedUnique} from "./utils/unique.js";
|
import {orderedUnique} from "./utils/unique.js";
|
||||||
|
|
||||||
const ROOMALIAS_PATTERN = /^#([^:]*):(.+)$/;
|
const ROOMALIAS_PATTERN = /^#([^:]*):(.+)$/;
|
||||||
const ROOMID_PATTERN = /^!([^:]*):(.+)$/;
|
const ROOMID_PATTERN = /^!([^:]*)(:(.+))?$/; // As of room version 12, room IDs don't have domains
|
||||||
const USERID_PATTERN = /^@([^:]+):(.+)$/;
|
const USERID_PATTERN = /^@([^:]+):(.+)$/;
|
||||||
const EVENTID_PATTERN = /^$([^:]+):(.+)$/;
|
const EVENTID_PATTERN = /^$([^:]+):(.+)$/;
|
||||||
const GROUPID_PATTERN = /^\+([^:]+):(.+)$/;
|
const GROUPID_PATTERN = /^\+([^:]+):(.+)$/;
|
||||||
@@ -152,7 +152,7 @@ export class Link {
|
|||||||
}
|
}
|
||||||
matches = ROOMID_PATTERN.exec(identifier);
|
matches = ROOMID_PATTERN.exec(identifier);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
const server = matches[2];
|
const server = matches[3]; // group 2 is an optional over `:domain`, group 3 is just `domain`
|
||||||
const localPart = matches[1];
|
const localPart = matches[1];
|
||||||
return new Link(clientId, viaServers, IdentifierKind.RoomId, localPart, server, webInstances, eventId);
|
return new Link(clientId, viaServers, IdentifierKind.RoomId, localPart, server, webInstances, eventId);
|
||||||
}
|
}
|
||||||
@@ -166,12 +166,19 @@ export class Link {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(clientId, viaServers, identifierKind, localPart, server, webInstances, eventId) {
|
constructor(clientId, viaServers, identifierKind, localPart, server, webInstances, eventId) {
|
||||||
const servers = [server];
|
const servers = [];
|
||||||
|
if (server !== undefined) {
|
||||||
|
servers.push(server); // v12 rooms don't have domains, and therefore no server
|
||||||
|
}
|
||||||
servers.push(...viaServers);
|
servers.push(...viaServers);
|
||||||
this.webInstances = webInstances;
|
this.webInstances = webInstances;
|
||||||
this.servers = orderedUnique(servers);
|
this.servers = orderedUnique(servers);
|
||||||
this.identifierKind = identifierKind;
|
this.identifierKind = identifierKind;
|
||||||
|
if (identifierKind === IdentifierKind.RoomId && !server) {
|
||||||
|
this.identifier = `${asPrefix(identifierKind)}${localPart}`;
|
||||||
|
} else {
|
||||||
this.identifier = `${asPrefix(identifierKind)}${localPart}:${server}`;
|
this.identifier = `${asPrefix(identifierKind)}${localPart}:${server}`;
|
||||||
|
}
|
||||||
this.eventId = eventId;
|
this.eventId = eventId;
|
||||||
this.clientId = clientId;
|
this.clientId = clientId;
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-8
@@ -30,14 +30,14 @@ export class RootView extends TemplateView {
|
|||||||
t.mapView(vm => vm.createLinkViewModel, vm => vm ? new CreateLinkView(vm) : null),
|
t.mapView(vm => vm.createLinkViewModel, vm => vm ? new CreateLinkView(vm) : null),
|
||||||
t.mapView(vm => vm.loadServerPolicyViewModel, vm => vm ? new LoadServerPolicyView(vm) : null),
|
t.mapView(vm => vm.loadServerPolicyViewModel, vm => vm ? new LoadServerPolicyView(vm) : null),
|
||||||
t.div({className: "footer"}, [
|
t.div({className: "footer"}, [
|
||||||
t.p(t.img({src: "images/matrix-logo.svg"})),
|
t.p([
|
||||||
t.p(["This invite uses ", externalLink(t, "https://matrix.org", "Matrix"), ", an open network for secure, decentralized communication."]),
|
"© 2026 ",
|
||||||
t.ul({className: "links"}, [
|
t.a({href: "https://ztfr.eu"}, "Zeitfresser"),
|
||||||
t.li(externalLink(t, "https://github.com/matrix-org/matrix.to", "GitHub project")),
|
" | Powered by ",
|
||||||
t.li(externalLink(t, "https://github.com/matrix-org/matrix.to/tree/main/src/open/clients", "Add your app")),
|
externalLink(t, "https://github.com/matrix-org/matrix.to", "Matrix-to")
|
||||||
t.li({className: {hidden: vm => !vm.hasPreferences}},
|
]),
|
||||||
t.button({className: "text", onClick: () => vm.clearPreferences()}, "Clear preferences")),
|
t.p({className: {hidden: vm => !vm.hasPreferences}}, [
|
||||||
t.li(t.a({href: "#/disclaimer/"}, "Disclaimer")),
|
t.button({className: "text", onClick: () => { vm.clearPreferences(); location.reload(); }}, "Clear preferences")
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -18,13 +18,15 @@ import {Maturity, Platform, LinkKind,
|
|||||||
FDroidLink, AppleStoreLink, PlayStoreLink, WebsiteLink} from "../types.js";
|
FDroidLink, AppleStoreLink, PlayStoreLink, WebsiteLink} from "../types.js";
|
||||||
|
|
||||||
const trustedWebInstances = [
|
const trustedWebInstances = [
|
||||||
"app.element.io", // first one is the default one
|
"chat.ztfr.eu", // Zeitfresser ist der gesetzte Standard
|
||||||
|
"app.element.io",
|
||||||
"develop.element.io",
|
"develop.element.io",
|
||||||
"chat.fedoraproject.org",
|
"chat.fedoraproject.org",
|
||||||
"chat.fosdem.org",
|
"chat.fosdem.org",
|
||||||
"chat.mozilla.org",
|
"chat.mozilla.org",
|
||||||
"webchat.kde.org",
|
"webchat.kde.org",
|
||||||
"app.gitter.im",
|
"app.gitter.im",
|
||||||
|
"chat.blender.org",
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,12 +83,15 @@ export class Element {
|
|||||||
|
|
||||||
const isWebPlatform = platform === Platform.DesktopWeb || platform === Platform.MobileWeb;
|
const isWebPlatform = platform === Platform.DesktopWeb || platform === Platform.MobileWeb;
|
||||||
if (isWebPlatform || platform === Platform.iOS) {
|
if (isWebPlatform || platform === Platform.iOS) {
|
||||||
|
// Standardmäßig deine Instanz nehmen
|
||||||
let instanceHost = trustedWebInstances[0];
|
let instanceHost = trustedWebInstances[0];
|
||||||
// we use app.element.io which iOS will intercept, but it likely won't intercept any other trusted instances
|
|
||||||
// so only use a preferred web instance for true web links.
|
// Falls der Nutzer über den "Change"-Dialog eine bevorzugte Instanz
|
||||||
|
// oder eine Custom-URL gewählt hat, nutzen wir diese:
|
||||||
if (isWebPlatform && preferredWebInstance) {
|
if (isWebPlatform && preferredWebInstance) {
|
||||||
instanceHost = preferredWebInstance;
|
instanceHost = preferredWebInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `https://${instanceHost}/#/${fragmentPath}`;
|
return `https://${instanceHost}/#/${fragmentPath}`;
|
||||||
} else if (platform === Platform.Linux || platform === Platform.Windows || platform === Platform.macOS) {
|
} else if (platform === Platform.Linux || platform === Platform.Windows || platform === Platform.macOS) {
|
||||||
return `element://vector/webapp/#/${fragmentPath}`;
|
return `element://vector/webapp/#/${fragmentPath}`;
|
||||||
@@ -99,8 +104,8 @@ export class Element {
|
|||||||
getCopyString(platform, link) {}
|
getCopyString(platform, link) {}
|
||||||
getInstallLinks(platform) {
|
getInstallLinks(platform) {
|
||||||
switch (platform) {
|
switch (platform) {
|
||||||
case Platform.iOS: return [new AppleStoreLink('vector', 'id1083446067')];
|
case Platform.iOS: return [new AppleStoreLink('element-x-secure-chat-call', 'id1631335820')];
|
||||||
case Platform.Android: return [new PlayStoreLink('im.vector.app'), new FDroidLink('im.vector.app')];
|
case Platform.Android: return [new PlayStoreLink('io.element.android.x'), new FDroidLink('io.element.android.x')];
|
||||||
default: return [new WebsiteLink("https://element.io/download")];
|
default: return [new WebsiteLink("https://element.io/download")];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,6 +115,8 @@ export class Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getPreferredWebInstance(link) {
|
getPreferredWebInstance(link) {
|
||||||
|
// Hier geben wir dem System die Erlaubnis, gespeicherte Präferenzen zu finden.
|
||||||
|
// Wenn keine da sind, greift oben automatisch trustedWebInstances[0].
|
||||||
const idx = trustedWebInstances.indexOf(link.webInstances[this.id])
|
const idx = trustedWebInstances.indexOf(link.webInstances[this.id])
|
||||||
return idx === -1 ? undefined : trustedWebInstances[idx];
|
return idx === -1 ? undefined : trustedWebInstances[idx];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user