Fixeds and enhancements
Some checks failed
Deploy SingleChat / deploy (push) Has been cancelled

This commit is contained in:
Torsten Schulz (local)
2026-06-17 15:44:11 +02:00
parent 10e6e7a80a
commit 5d4129b5b3
44 changed files with 151 additions and 109 deletions

View File

@@ -32,7 +32,7 @@
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="icon" type="image/png" href="/appicon.png">
<script type="application/ld+json" id="seo-json-ld">{"@context":"https://schema.org","@type":"WebSite","name":"SingleChat","alternateName":"YPChat","url":"https://www.ypchat.net/","description":"Kostenloser Single Chat ohne lange Registrierung: Profil starten, Singles kennenlernen, privat chatten und Bilder sicher austauschen.","inLanguage":"de-DE"}</script>
<script type="application/ld+json" id="seo-json-ld">{"@context":"https://schema.org","@type":"WebSite","name":"SingleChat","alternateName":"ypchat.net","url":"https://www.ypchat.net/","description":"Kostenloser Single Chat ohne lange Registrierung: Profil starten, Singles kennenlernen, privat chatten und Bilder sicher austauschen.","inLanguage":"de-DE"}</script>
</head>
<body>
<div id="app"></div>

View File

@@ -1,11 +1,11 @@
{
"name": "singlechat-client",
"name": "ypchat-client",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "singlechat-client",
"name": "ypchat-client",
"version": "1.0.0",
"dependencies": {
"@unhead/vue": "^2.0.19",

View File

@@ -1,5 +1,5 @@
{
"name": "singlechat-client",
"name": "ypchat-client",
"version": "1.0.0",
"type": "module",
"scripts": {

View File

@@ -32,7 +32,7 @@
title="Foto aufnehmen"
:disabled="!hasConversation || isCameraStarting"
>
<span aria-hidden="true">📷</span>
<span class="camera-button-icon" aria-hidden="true">📷</span>
</button>
<div v-if="showSmileys" class="smiley-bar">
@@ -380,15 +380,22 @@ onBeforeUnmount(() => {
<style scoped>
.camera-button {
width: 35px;
height: 35px;
width: 40px;
height: 40px;
padding: 0;
border: 1px solid #cdd8d0;
border-radius: 8px;
background: #ffffff;
display: inline-grid;
place-items: center;
background: linear-gradient(180deg, #fdfefd 0%, #edf4ef 100%);
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 18px;
}
.camera-button-icon {
display: block;
font-size: 20px;
line-height: 1;
}
.camera-button:disabled {

View File

@@ -1,7 +1,7 @@
<template>
<div class="landing-login">
<section class="landing-login-intro">
<p class="landing-login-eyebrow">SingleChat</p>
<p class="landing-login-eyebrow">YpChat</p>
<h2>Direkt in den Chat</h2>
<p class="landing-login-copy">
Kompakt, schnell und ohne Umwege. Erstelle dein Profil und starte sofort eine Unterhaltung.
@@ -11,7 +11,7 @@
<span>Bildaustausch</span>
<span>Kompakte Bedienung</span>
</div>
<nav class="landing-login-topic-links" aria-label="SingleChat Themen">
<nav class="landing-login-topic-links" aria-label="YpChat Themen">
<router-link to="/kostenloser-single-chat">Kostenloser Single Chat</router-link>
<router-link to="/single-chat-ohne-anmeldung">Ohne lange Anmeldung</router-link>
<router-link to="/single-treff-chat">Single Treff Chat</router-link>

View File

@@ -107,9 +107,9 @@ function statusLabel(status) {
<style scoped>
.video-dock {
width: min(20vw, 320px);
min-width: 220px;
max-width: 320px;
width: min(16vw, 240px);
min-width: 180px;
max-width: 240px;
padding: 12px;
border-left: 1px solid #dfe6e1;
background: linear-gradient(180deg, #f5f8f6 0%, #edf3ef 100%);
@@ -191,8 +191,8 @@ function statusLabel(status) {
@media (max-width: 1100px) {
.video-dock {
width: 240px;
min-width: 240px;
width: 200px;
min-width: 200px;
}
}

View File

@@ -69,7 +69,7 @@ const homeSchema = {
'@context': 'https://schema.org',
'@type': 'WebSite',
name: 'SingleChat',
alternateName: 'YPChat',
alternateName: 'ypchat.net',
url: `${SITE_URL}/`,
description: 'Kostenloser Single Chat ohne lange Registrierung. Lerne Singles kennen, chatte privat und tausche Bilder sicher aus.',
inLanguage: 'de-DE'
@@ -347,7 +347,7 @@ const routes = [
meta: {
title: 'Datenschutzerklärung für Website und App - SingleChat',
description: 'Datenschutzerklärung für SingleChat und die Android-App mit Informationen zu Profilangaben, Nachrichten, Bildern und Sitzungsdaten.',
keywords: 'datenschutz singlechat, privacy policy chat app, chat datenschutz, android app datenschutz',
keywords: 'datenschutz ypchat, privacy policy chat app, chat datenschutz, android app datenschutz',
ogTitle: 'Datenschutzerklärung für Website und App - SingleChat',
ogDescription: 'Informationen zur Datenverarbeitung bei SingleChat und in der Android-App.',
ogType: 'website',

View File

@@ -8,6 +8,15 @@ const MAX_VIDEO_CONNECTIONS_DEFAULT = 3;
const VIDEO_TERMINAL_STATUSES = new Set(['rejected', 'cancelled', 'ended', 'failed']);
const VIDEO_LIVE_STATUSES = new Set(['ringing', 'connecting', 'active']);
const WEBRTC_CONNECTION_STATES = new Set(['new', 'connecting', 'connected', 'disconnected', 'failed', 'closed']);
const VIDEO_STATUS_ORDER = {
ringing: 1,
connecting: 2,
active: 3,
rejected: 4,
cancelled: 4,
ended: 4,
failed: 4
};
function createEmptySearchData() {
return {
@@ -139,6 +148,34 @@ export const useChatStore = defineStore('chat', () => {
};
}
function getVideoStatusRank(status) {
return VIDEO_STATUS_ORDER[status] || 0;
}
function parseVideoTimestamp(value) {
const time = Date.parse(value || '');
return Number.isFinite(time) ? time : 0;
}
function shouldIgnoreVideoSessionUpdate(currentSession, nextSession) {
if (!currentSession) return false;
const currentUpdatedAt = parseVideoTimestamp(currentSession.updatedAt || currentSession.createdAt);
const nextUpdatedAt = parseVideoTimestamp(nextSession.updatedAt || nextSession.createdAt);
if (nextUpdatedAt && currentUpdatedAt && nextUpdatedAt < currentUpdatedAt) {
return true;
}
if (
nextUpdatedAt === currentUpdatedAt &&
getVideoStatusRank(nextSession.status) < getVideoStatusRank(currentSession.status)
) {
return true;
}
return false;
}
function getRemoteStream(callId) {
return remoteStreams.value[callId] || null;
}
@@ -209,8 +246,13 @@ export const useChatStore = defineStore('chat', () => {
const index = videoSessions.value.findIndex((entry) => entry.callId === next.callId);
if (index >= 0) {
const current = videoSessions.value[index];
if (shouldIgnoreVideoSessionUpdate(current, next)) {
return;
}
videoSessions.value[index] = {
...videoSessions.value[index],
...current,
...next
};
videoSessions.value = [...videoSessions.value];

View File

@@ -633,7 +633,7 @@ a {
background: linear-gradient(180deg, rgba(238, 245, 240, 0.92) 0%, rgba(247, 250, 248, 0.88) 100%);
flex-shrink: 0;
display: grid;
grid-template-columns: minmax(0, 1fr) auto auto auto;
grid-template-columns: minmax(0, 1fr) auto auto auto auto;
gap: 8px;
align-items: center;
position: relative;
@@ -868,7 +868,7 @@ a {
}
.chat-input-container {
grid-template-columns: minmax(0, 1fr) auto auto;
grid-template-columns: minmax(0, 1fr) auto auto auto auto;
}
.chat-input-container button:not(.no-style) {

View File

@@ -5,8 +5,8 @@
<aside class="app-sidebar">
<div class="sidebar-brand">
<div class="sidebar-brand-head">
<span class="app-brand-mark sidebar-brand-mark" aria-hidden="true">S</span>
<strong>SingleChat</strong>
<span class="app-brand-mark sidebar-brand-mark" aria-hidden="true">Y</span>
<strong>YpChat</strong>
</div>
<span>Online Chat</span>
</div>
@@ -51,7 +51,7 @@
<span class="profile-avatar">{{ userInitials }}</span>
<span>
<strong>{{ chatStore.userName }}</strong>
<small>{{ chatStore.country || 'SingleChat Member' }}</small>
<small>{{ chatStore.country || 'YpChat Member' }}</small>
</span>
</div>
</aside>
@@ -156,9 +156,9 @@
<template v-else>
<header class="header">
<div class="app-brand">
<span class="app-brand-mark">S</span>
<span class="app-brand-mark">Y</span>
<div class="app-brand-copy">
<span class="app-brand-eyebrow">SingleChat</span>
<span class="app-brand-eyebrow">YpChat</span>
<h1>Chat</h1>
</div>
</div>
@@ -195,12 +195,12 @@ import FloatingVideoWindow from '../components/FloatingVideoWindow.vue';
const chatStore = useChatStore();
const userInitials = computed(() => {
return (chatStore.userName || 'SC')
return (chatStore.userName || 'YP')
.split(/\s+/)
.filter(Boolean)
.slice(0, 2)
.map(part => part.charAt(0).toUpperCase())
.join('') || 'SC';
.join('') || 'YP';
});
const pageTitle = computed(() => {

View File

@@ -4,7 +4,7 @@
<router-link to="/" class="app-brand app-brand-link">
<span class="app-brand-mark">S</span>
<div class="app-brand-copy">
<span class="app-brand-eyebrow">SingleChat</span>
<span class="app-brand-eyebrow">YpChat</span>
<h1>FAQ</h1>
</div>
</router-link>
@@ -90,4 +90,3 @@ import ImprintContainer from '../components/ImprintContainer.vue';
text-decoration: none;
}
</style>

View File

@@ -4,7 +4,7 @@
<router-link to="/" class="app-brand app-brand-link">
<span class="app-brand-mark">S</span>
<div class="app-brand-copy">
<span class="app-brand-eyebrow">SingleChat</span>
<span class="app-brand-eyebrow">YpChat</span>
<h1>Feedback</h1>
</div>
</router-link>

View File

@@ -4,7 +4,7 @@
<router-link to="/" class="app-brand app-brand-link">
<span class="app-brand-mark">S</span>
<div class="app-brand-copy">
<span class="app-brand-eyebrow">SingleChat</span>
<span class="app-brand-eyebrow">YpChat</span>
<h1>Ratgeber</h1>
</div>
</router-link>
@@ -77,7 +77,7 @@
</p>
<p class="content-meta">
Redaktion: SingleChat Team · Zuletzt aktualisiert: 07.05.2026
Redaktion: YpChat Team · Zuletzt aktualisiert: 07.05.2026
</p>
</main>

View File

@@ -4,7 +4,7 @@
<router-link to="/" class="app-brand app-brand-link">
<span class="app-brand-mark">S</span>
<div class="app-brand-copy">
<span class="app-brand-eyebrow">SingleChat</span>
<span class="app-brand-eyebrow">YpChat</span>
<h1>Ratgeber</h1>
</div>
</router-link>
@@ -15,7 +15,7 @@
<h2>Ratgeber: Sicher und entspannt chatten</h2>
<p>
In unserem Ratgeber findest du praxisnahe Tipps rund um privaten Chat, Profilgestaltung und digitale Sicherheit.
Alle Inhalte sind speziell fuer SingleChat-Nutzer geschrieben und werden laufend erweitert.
Alle Inhalte sind speziell fuer YpChat-Nutzer geschrieben und werden laufend erweitert.
</p>
<p>
Wenn du neu im Chat bist, starte am besten mit dem Leitfaden zur ersten Unterhaltung und arbeite dich dann zu
@@ -77,7 +77,7 @@
</section>
<p class="content-meta">
Redaktion: SingleChat Team · Zuletzt aktualisiert: 07.05.2026
Redaktion: YpChat Team · Zuletzt aktualisiert: 07.05.2026
</p>
</main>

View File

@@ -4,7 +4,7 @@
<router-link to="/" class="app-brand app-brand-link">
<span class="app-brand-mark">S</span>
<div class="app-brand-copy">
<span class="app-brand-eyebrow">SingleChat</span>
<span class="app-brand-eyebrow">YpChat</span>
<h1>Ratgeber</h1>
</div>
</router-link>
@@ -76,7 +76,7 @@
</p>
<p class="content-meta">
Redaktion: SingleChat Team · Zuletzt aktualisiert: 07.05.2026
Redaktion: YpChat Team · Zuletzt aktualisiert: 07.05.2026
</p>
</main>

View File

@@ -4,7 +4,7 @@
<router-link to="/" class="app-brand app-brand-link">
<span class="app-brand-mark">S</span>
<div class="app-brand-copy">
<span class="app-brand-eyebrow">SingleChat</span>
<span class="app-brand-eyebrow">YpChat</span>
<h1>Ratgeber</h1>
</div>
</router-link>
@@ -63,7 +63,7 @@
</p>
<p class="content-meta">
Redaktion: SingleChat Team · Zuletzt aktualisiert: 07.05.2026
Redaktion: YpChat Team · Zuletzt aktualisiert: 07.05.2026
</p>
</main>

View File

@@ -4,7 +4,7 @@
<router-link to="/" class="app-brand app-brand-link">
<span class="app-brand-mark">S</span>
<div class="app-brand-copy">
<span class="app-brand-eyebrow">SingleChat</span>
<span class="app-brand-eyebrow">YpChat</span>
<h1>Ratgeber</h1>
</div>
</router-link>
@@ -63,7 +63,7 @@
</p>
<p class="content-meta">
Redaktion: SingleChat Team · Zuletzt aktualisiert: 07.05.2026
Redaktion: YpChat Team · Zuletzt aktualisiert: 07.05.2026
</p>
</main>

View File

@@ -2,7 +2,7 @@
<div class="mockup-page">
<header class="mockup-page-header">
<div>
<p class="mockup-page-eyebrow">SingleChat Redesign</p>
<p class="mockup-page-eyebrow">YpChat Redesign</p>
<h1>Mockup-Vergleich</h1>
</div>
<p class="mockup-page-copy">
@@ -28,7 +28,7 @@
<div class="mockup-brand-mark">S</div>
<div>
<p class="mockup-eyebrow">Design Preview</p>
<h3>SingleChat</h3>
<h3>YpChat</h3>
</div>
</div>
@@ -148,7 +148,7 @@
<div class="mockup-mobile-device mockup-mobile-device-polished">
<div class="mockup-mobile-top">
<span>SingleChat</span>
<span>YpChat</span>
<span class="mockup-mobile-pill">3</span>
</div>
<div class="mockup-mobile-chat-header">

View File

@@ -4,7 +4,7 @@
<router-link to="/" class="app-brand app-brand-link">
<span class="app-brand-mark">S</span>
<div class="app-brand-copy">
<span class="app-brand-eyebrow">SingleChat</span>
<span class="app-brand-eyebrow">YpChat</span>
<h1>Partner</h1>
</div>
</router-link>

View File

@@ -4,7 +4,7 @@
<router-link to="/" class="app-brand app-brand-link">
<span class="app-brand-mark">S</span>
<div class="app-brand-copy">
<span class="app-brand-eyebrow">SingleChat</span>
<span class="app-brand-eyebrow">YpChat</span>
<h1>Datenschutz</h1>
</div>
</router-link>
@@ -14,7 +14,7 @@
<main class="content-page">
<h2>Datenschutzerklärung für Website und App</h2>
<p>
Diese Datenschutzerklärung gilt für die Website und die Android-App von SingleChat unter
Diese Datenschutzerklärung gilt für die Website und die Android-App von YpChat unter
der Domain <strong>www.ypchat.net</strong>.
</p>
<p>

View File

@@ -4,7 +4,7 @@
<router-link to="/" class="app-brand app-brand-link">
<span class="app-brand-mark">S</span>
<div class="app-brand-copy">
<span class="app-brand-eyebrow">SingleChat</span>
<span class="app-brand-eyebrow">YpChat</span>
<h1>Regeln</h1>
</div>
</router-link>
@@ -85,4 +85,3 @@ import ImprintContainer from '../components/ImprintContainer.vue';
text-decoration: none;
}
</style>

View File

@@ -4,7 +4,7 @@
<router-link to="/" class="app-brand app-brand-link">
<span class="app-brand-mark">S</span>
<div class="app-brand-copy">
<span class="app-brand-eyebrow">SingleChat</span>
<span class="app-brand-eyebrow">YpChat</span>
<h1>Sicherheit</h1>
</div>
</router-link>
@@ -14,7 +14,7 @@
<main class="content-page">
<h2>Sicherheit &amp; Privatsphäre</h2>
<p>
SingleChat ist auf schnellen Einstieg ausgelegt – trotzdem ist uns Sicherheit wichtig. Diese Hinweise helfen dir,
YpChat ist auf schnellen Einstieg ausgelegt – trotzdem ist uns Sicherheit wichtig. Diese Hinweise helfen dir,
im privaten und anonymen Chat deine Privatsphäre zu schützen und gute Entscheidungen zu treffen.
</p>

View File

@@ -4,7 +4,7 @@
<router-link to="/" class="app-brand app-brand-link">
<span class="app-brand-mark">S</span>
<div class="app-brand-copy">
<span class="app-brand-eyebrow">SingleChat</span>
<span class="app-brand-eyebrow">YpChat</span>
<h1>{{ landing.heading }}</h1>
</div>
</router-link>
@@ -27,7 +27,7 @@
</div>
</section>
<section class="topic-grid" aria-label="SingleChat Vorteile">
<section class="topic-grid" aria-label="YpChat Vorteile">
<article
v-for="section in landing.sections"
:key="section.title"
@@ -42,7 +42,7 @@
<h3>Passende Themen im Single Chat</h3>
<p>
Viele Nutzer suchen nach einem kostenlosen Single Chat, einem Chat ohne lange Anmeldung oder einem Single Treff
fuer neue Kontakte. SingleChat buendelt diese Einstiege auf einer Plattform: schnell starten, privat schreiben,
fuer neue Kontakte. YpChat buendelt diese Einstiege auf einer Plattform: schnell starten, privat schreiben,
respektvoll bleiben.
</p>
<ul>
@@ -65,7 +65,7 @@ import ImprintContainer from '../components/ImprintContainer.vue';
const route = useRoute();
const landing = computed(() => route.meta.landing || {
heading: 'SingleChat',
heading: 'YpChat',
intro: 'Kostenloser Single Chat fuer private Gespraeche und neue Kontakte.',
sections: [],
links: [{ to: '/', label: 'Chat starten' }]