Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 |
@@ -56,6 +56,8 @@ The matrix.to URL scheme is
|
||||
The #/ component is mandatory and exists to avoid leaking the target URL to the
|
||||
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
|
||||
target user has been invited: these links cannot be assumed to work for all
|
||||
visitors.
|
||||
|
||||
+83
-71
@@ -1,98 +1,110 @@
|
||||
.ClientListView h2 {
|
||||
text-align: center;
|
||||
margin: 18px 0;
|
||||
}
|
||||
|
||||
.ClientListView .filterOption {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 8px 0;
|
||||
margin: 24px 0;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ClientView {
|
||||
border: 1px solid #E6E6E6;
|
||||
border-radius: 8px;
|
||||
background: var(--app-background);
|
||||
border: 1px solid var(--borders);
|
||||
border-radius: 4px;
|
||||
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 {
|
||||
border: 3px solid var(--link);
|
||||
box-shadow: 0px 8px 4px rgba(0, 0, 0, 0.05);
|
||||
border-color: var(--ztfr-purple);
|
||||
background: rgba(189, 147, 249, 0.05);
|
||||
}
|
||||
|
||||
.ClientView .hostedBanner {
|
||||
text-align: center;
|
||||
margin-bottom: 29px;
|
||||
padding: 4px 0;
|
||||
line-height: 20px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 20px;
|
||||
padding: 6px 0;
|
||||
border-radius: 4px;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
background-color: var(--lightgrey);
|
||||
font-size: 13px;
|
||||
background-color: var(--ztfr-purple);
|
||||
color: var(--app-background);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.ClientView .header {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.ClientView .description {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.ClientView h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
.ClientView .header { display: flex; align-items: flex-start; }
|
||||
.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 .clientIcon {
|
||||
border-radius: 8px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
border-radius: 4px;
|
||||
background-color: #ffffff;
|
||||
padding: 4px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-left: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ClientView .platforms {
|
||||
background-image: url('../images/platform-icon.svg');
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 center;
|
||||
padding-left: 28px;
|
||||
}
|
||||
|
||||
.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');
|
||||
margin-top: 12px;
|
||||
font-size: 12px;
|
||||
color: var(--grey);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.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; /* Erlaubt dem Bild, zu skalieren */
|
||||
max-width: 100%; /* Verhindert das Rausragen */
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ClientView .actions img {
|
||||
max-width: 160px; /* Begrenzt die Breite der Store-Buttons (Google Play / F-Droid) */
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 5px auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
.ClientView {
|
||||
padding: 15px; /* Weniger Padding mobil */
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.ClientView .header {
|
||||
flex-direction: column; /* Stapelt Icon und Text mobil untereinander */
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ClientView .clientIcon {
|
||||
margin: 0 0 15px 0; /* Icon zentrieren */
|
||||
}
|
||||
}
|
||||
|
||||
+158
-158
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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.
|
||||
Modified 2026 for Zeitfresser Matrix Community Look & Mobile Fixes
|
||||
*/
|
||||
|
||||
@import url('spinner.css');
|
||||
@@ -20,57 +9,63 @@ limitations under the License.
|
||||
@import url('create.css');
|
||||
@import url('open.css');
|
||||
|
||||
/* Globaler Fix für Box-Berechnungen */
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
--app-background: #f4f4f4;
|
||||
--background: #ffffff;
|
||||
--foreground: #000000;
|
||||
--font: #333333;
|
||||
--grey: #666666;
|
||||
--accent: #0098d4;
|
||||
--error: #d6001c;
|
||||
--link: #0098d4;
|
||||
--borders: #f4f4f4;
|
||||
--lightgrey: #E6E6E6;
|
||||
--app-background: #1e1f29; /* Tief-Anthrazit der Webseite */
|
||||
--background: #282a36; /* Hintergrund der Card */
|
||||
--foreground: #f7f7fa; /* Reines Highlight-Weiß */
|
||||
--font: #bdc3c7; /* Fließtext-Grau */
|
||||
--grey: #64748b; /* Dunkles Grau für Identifier */
|
||||
--accent: #0dbd8b; /* Matrix-Green */
|
||||
--ztfr-purple: #bd93f9; /* Das Zeitfresser-Lila Akzent */
|
||||
--error: #ff5555;
|
||||
--link: #f7f7fa;
|
||||
--borders: #2f313d;
|
||||
--lightgrey: #383a59;
|
||||
--spinner-stroke-size: 2px;
|
||||
--sub-text: #bdc3c7;
|
||||
}
|
||||
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--app-background);
|
||||
background-image: url('../images/background.svg');
|
||||
background-attachment: fixed;
|
||||
background-repeat: no-repeat;
|
||||
background-size: auto;
|
||||
background-position: center -50px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
background-image: none !important;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
color: var(--font);
|
||||
padding: 120px 0 0 0;
|
||||
padding: 80px 20px 0 20px;
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
noscript {
|
||||
display: block;
|
||||
padding: 20px;
|
||||
h1, h2, h3 {
|
||||
color: var(--foreground);
|
||||
letter-spacing: -0.5px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
p { line-height: 150%; }
|
||||
a { text-decoration: none; }
|
||||
p {
|
||||
line-height: 1.7;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
h1 { font-size: 24px; }
|
||||
h2 { font-size: 21px; }
|
||||
h3 { font-size: 16px; }
|
||||
a { text-decoration: none; color: var(--link); }
|
||||
|
||||
body,
|
||||
button,
|
||||
input,
|
||||
textarea {
|
||||
font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
|
||||
body, button, input, textarea {
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@@ -78,13 +73,14 @@ button, input[type=submit] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button, input {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
input[type="checkbox"], input[type="radio"] {
|
||||
margin: 0 8px 0 0;
|
||||
/* Die zentrale Kachel */
|
||||
.card {
|
||||
background-color: var(--background);
|
||||
border-radius: 4px;
|
||||
border-left: 4px solid var(--ztfr-purple);
|
||||
box-shadow: 0px 20px 40px rgba(0, 0, 0, 0.3);
|
||||
padding: 2.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.RootView {
|
||||
@@ -93,131 +89,135 @@ input[type="checkbox"], input[type="radio"] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.card {
|
||||
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;
|
||||
}
|
||||
|
||||
/* Buttons: Eckig & Kontrastreich */
|
||||
.primary, .secondary {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
padding: 12px 8px;
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.secondary {
|
||||
background: var(--background);
|
||||
color: var(--link);
|
||||
border: 1px solid var(--link);
|
||||
border-radius: 32px;
|
||||
padding: 14px 20px;
|
||||
margin: 4px 0 !important;
|
||||
display: block;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
transition: all 0.2s ease;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.primary {
|
||||
background: var(--link);
|
||||
color: var(--background);
|
||||
border-radius: 32px;
|
||||
}
|
||||
|
||||
.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 {
|
||||
background: var(--foreground);
|
||||
color: var(--app-background) !important;
|
||||
border-radius: 4px;
|
||||
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);
|
||||
}
|
||||
|
||||
/* Fix für Button-Container (entfernt versteckte Gaps) */
|
||||
.actions,
|
||||
.ClientView .actions,
|
||||
.ClientListView .actions,
|
||||
.CustomInstanceView .actions {
|
||||
display: flex !important;
|
||||
flex-direction: column !important;
|
||||
gap: 0px !important;
|
||||
}
|
||||
|
||||
/* Entfernt den Abstand beim letzten Button in einer Gruppe für saubere Optik */
|
||||
.actions > *:last-child {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
/* Input Felder: Dunkel statt Weiß */
|
||||
input[type='text'].large {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
background: var(--background);
|
||||
border: 1px solid var(--foreground);
|
||||
border-radius: 16px;
|
||||
padding: 14px;
|
||||
background: #1a1a1a !important;
|
||||
border: 1px solid var(--borders);
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.fullwidth {
|
||||
display: block;
|
||||
width: 100%;
|
||||
color: var(--foreground);
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.LoadServerPolicyView {
|
||||
display: flex;
|
||||
.footer {
|
||||
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 {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 12px;
|
||||
.footer ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.LoadServerPolicyView h2 {
|
||||
margin-top: 0;
|
||||
.footer li {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid rgba(189, 195, 199, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.footer a:hover {
|
||||
color: var(--foreground) !important;
|
||||
border-bottom-color: var(--ztfr-purple) !important;
|
||||
}
|
||||
|
||||
.footer button,
|
||||
.footer input[type="submit"],
|
||||
.ClientListView button.change,
|
||||
.PreviewView button.change {
|
||||
background: none !important;
|
||||
border: none !important;
|
||||
color: var(--grey) !important;
|
||||
padding: 0 !important;
|
||||
font-family: inherit !important;
|
||||
font-size: inherit !important;
|
||||
cursor: pointer !important;
|
||||
border-bottom: 1px solid rgba(189, 195, 199, 0.3) !important;
|
||||
}
|
||||
|
||||
.footer button:hover {
|
||||
color: var(--foreground) !important;
|
||||
border-bottom-color: var(--ztfr-purple) !important;
|
||||
}
|
||||
|
||||
/* SPEZIELLE MOBILE ANPASSUNGEN */
|
||||
@media screen and (max-width: 480px) {
|
||||
body {
|
||||
padding: 40px 10px 0 10px;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 1.5rem;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
+54
-89
@@ -4,130 +4,95 @@
|
||||
}
|
||||
|
||||
.PreviewView h1 {
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
font-size: 26px;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 8px;
|
||||
word-wrap: anywhere;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.PreviewView .avatarContainer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.PreviewView .avatar {
|
||||
border-radius: 100%;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.PreviewView .mxSpace .avatar {
|
||||
border-radius: 12px;
|
||||
border-radius: 8px; /* Eckig */
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border: 3px solid var(--borders);
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.PreviewView .defaultAvatar {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 8px;
|
||||
background-color: var(--lightgrey);
|
||||
background-image: url('../images/chat-icon.svg');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 85%;
|
||||
}
|
||||
|
||||
.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;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.PreviewView .identifier {
|
||||
color: var(--grey);
|
||||
font-size: 12px;
|
||||
color: var(--ztfr-purple);
|
||||
font-family: monospace;
|
||||
font-size: 13px;
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.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;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.PreviewView .memberCount p:not(.placeholder) {
|
||||
padding: 4px 8px 4px 24px;
|
||||
border-radius: 14px;
|
||||
padding: 6px 12px 6px 28px;
|
||||
border-radius: 4px;
|
||||
color: var(--foreground);
|
||||
background-image: url(../images/member-icon.svg);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 2px center;
|
||||
background-position: 8px center;
|
||||
background-color: var(--lightgrey);
|
||||
}
|
||||
|
||||
.PreviewView .memberCount p.placeholder {
|
||||
height: 1.5em;
|
||||
width: 100px;
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.PreviewView .topic {
|
||||
font-size: 12px;
|
||||
color: var(--grey);
|
||||
margin: 32px 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%;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
color: var(--font);
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
/* Dark Mode Placeholders */
|
||||
.placeholder {
|
||||
border-radius: 1em;
|
||||
--flash-bg: #ddd;
|
||||
--flash-fg: #eee;
|
||||
background: linear-gradient(120deg,
|
||||
var(--flash-bg),
|
||||
var(--flash-bg) 10%,
|
||||
var(--flash-fg) calc(10% + 25px),
|
||||
var(--flash-bg) calc(10% + 50px)
|
||||
);
|
||||
border-radius: 4px;
|
||||
--flash-bg: #2f313d;
|
||||
--flash-fg: #383a59;
|
||||
background: linear-gradient(120deg, var(--flash-bg), var(--flash-bg) 10%, var(--flash-fg) calc(10% + 25px), var(--flash-bg) calc(10% + 50px));
|
||||
animation: flash 2s linear infinite;
|
||||
background-size: 200%;
|
||||
}
|
||||
|
||||
@keyframes flash {
|
||||
0% { background-position-x: 0; }
|
||||
50% { background-position-x: -80%; }
|
||||
51% { background-position-x: 80%; }
|
||||
100% { background-position-x: 0%; }
|
||||
100% { background-position-x: -200%; }
|
||||
}
|
||||
|
||||
.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 */
|
||||
}
|
||||
}
|
||||
|
||||
+12
-5
@@ -18,7 +18,7 @@ import {createEnum} from "./utils/enum.js";
|
||||
import {orderedUnique} from "./utils/unique.js";
|
||||
|
||||
const ROOMALIAS_PATTERN = /^#([^:]*):(.+)$/;
|
||||
const ROOMID_PATTERN = /^!([^:]*):(.+)$/;
|
||||
const ROOMID_PATTERN = /^!([^:]*)(:(.+))?$/; // As of room version 12, room IDs don't have domains
|
||||
const USERID_PATTERN = /^@([^:]+):(.+)$/;
|
||||
const EVENTID_PATTERN = /^$([^:]+):(.+)$/;
|
||||
const GROUPID_PATTERN = /^\+([^:]+):(.+)$/;
|
||||
@@ -92,7 +92,7 @@ export class Link {
|
||||
static validateIdentifier(identifier) {
|
||||
return !!(
|
||||
USERID_PATTERN.exec(identifier) ||
|
||||
ROOMALIAS_PATTERN.exec(identifier) ||
|
||||
ROOMALIAS_PATTERN.exec(identifier) ||
|
||||
ROOMID_PATTERN.exec(identifier) ||
|
||||
GROUPID_PATTERN.exec(identifier)
|
||||
);
|
||||
@@ -152,7 +152,7 @@ export class Link {
|
||||
}
|
||||
matches = ROOMID_PATTERN.exec(identifier);
|
||||
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];
|
||||
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) {
|
||||
const servers = [server];
|
||||
const servers = [];
|
||||
if (server !== undefined) {
|
||||
servers.push(server); // v12 rooms don't have domains, and therefore no server
|
||||
}
|
||||
servers.push(...viaServers);
|
||||
this.webInstances = webInstances;
|
||||
this.servers = orderedUnique(servers);
|
||||
this.identifierKind = identifierKind;
|
||||
this.identifier = `${asPrefix(identifierKind)}${localPart}:${server}`;
|
||||
if (identifierKind === IdentifierKind.RoomId && !server) {
|
||||
this.identifier = `${asPrefix(identifierKind)}${localPart}`;
|
||||
} else {
|
||||
this.identifier = `${asPrefix(identifierKind)}${localPart}:${server}`;
|
||||
}
|
||||
this.eventId = eventId;
|
||||
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.loadServerPolicyViewModel, vm => vm ? new LoadServerPolicyView(vm) : null),
|
||||
t.div({className: "footer"}, [
|
||||
t.p(t.img({src: "images/matrix-logo.svg"})),
|
||||
t.p(["This invite uses ", externalLink(t, "https://matrix.org", "Matrix"), ", an open network for secure, decentralized communication."]),
|
||||
t.ul({className: "links"}, [
|
||||
t.li(externalLink(t, "https://github.com/matrix-org/matrix.to", "GitHub project")),
|
||||
t.li(externalLink(t, "https://github.com/matrix-org/matrix.to/tree/main/src/open/clients", "Add your app")),
|
||||
t.li({className: {hidden: vm => !vm.hasPreferences}},
|
||||
t.button({className: "text", onClick: () => vm.clearPreferences()}, "Clear preferences")),
|
||||
t.li(t.a({href: "#/disclaimer/"}, "Disclaimer")),
|
||||
t.p([
|
||||
"© 2026 ",
|
||||
t.a({href: "https://ztfr.eu"}, "Zeitfresser"),
|
||||
" | Powered by ",
|
||||
externalLink(t, "https://github.com/matrix-org/matrix.to", "Matrix-to")
|
||||
]),
|
||||
t.p({className: {hidden: vm => !vm.hasPreferences}}, [
|
||||
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";
|
||||
|
||||
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",
|
||||
"chat.fedoraproject.org",
|
||||
"chat.fosdem.org",
|
||||
"chat.mozilla.org",
|
||||
"webchat.kde.org",
|
||||
"app.gitter.im",
|
||||
"chat.blender.org",
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -81,12 +83,15 @@ export class Element {
|
||||
|
||||
const isWebPlatform = platform === Platform.DesktopWeb || platform === Platform.MobileWeb;
|
||||
if (isWebPlatform || platform === Platform.iOS) {
|
||||
// Standardmäßig deine Instanz nehmen
|
||||
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) {
|
||||
instanceHost = preferredWebInstance;
|
||||
}
|
||||
|
||||
return `https://${instanceHost}/#/${fragmentPath}`;
|
||||
} else if (platform === Platform.Linux || platform === Platform.Windows || platform === Platform.macOS) {
|
||||
return `element://vector/webapp/#/${fragmentPath}`;
|
||||
@@ -99,8 +104,8 @@ export class Element {
|
||||
getCopyString(platform, link) {}
|
||||
getInstallLinks(platform) {
|
||||
switch (platform) {
|
||||
case Platform.iOS: return [new AppleStoreLink('vector', 'id1083446067')];
|
||||
case Platform.Android: return [new PlayStoreLink('im.vector.app'), new FDroidLink('im.vector.app')];
|
||||
case Platform.iOS: return [new AppleStoreLink('element-x-secure-chat-call', 'id1631335820')];
|
||||
case Platform.Android: return [new PlayStoreLink('io.element.android.x'), new FDroidLink('io.element.android.x')];
|
||||
default: return [new WebsiteLink("https://element.io/download")];
|
||||
}
|
||||
}
|
||||
@@ -110,6 +115,8 @@ export class Element {
|
||||
}
|
||||
|
||||
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])
|
||||
return idx === -1 ? undefined : trustedWebInstances[idx];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user