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' }]