diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 8738579..21982a2 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -34,8 +34,8 @@ android { applicationId = "de.ypchat.android" minSdk = 26 targetSdk = 36 - versionCode = 1 - versionName = "1.0.0" + versionCode = 2 + versionName = "1.1.0" } lint { diff --git a/android/app/release/app-release.aab b/android/app/release/app-release.aab index f830743..d6f8b55 100644 Binary files a/android/app/release/app-release.aab and b/android/app/release/app-release.aab differ diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index e0c2c5d..cf5372a 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,12 +1,13 @@  + @@ -20,4 +21,3 @@ - diff --git a/android/app/src/main/java/de/ypchat/android/ui/ChatViewModel.kt b/android/app/src/main/java/de/ypchat/android/ui/ChatViewModel.kt index 512d4c9..fc2ea63 100644 --- a/android/app/src/main/java/de/ypchat/android/ui/ChatViewModel.kt +++ b/android/app/src/main/java/de/ypchat/android/ui/ChatViewModel.kt @@ -36,6 +36,7 @@ class ChatViewModel(private val repository: ChatRepository) : ViewModel() { fun openConversation(userName: String) = repository.openConversation(userName) fun closeConversation() = repository.closeConversation() fun sendMessage(text: String) = repository.sendMessage(text) + fun setImageUploadMessage(message: String) = repository.setImageUploadState(false, message) fun sendImage(context: Context, uri: Uri) { val target = state.value.currentConversation ?: return viewModelScope.launch { diff --git a/android/app/src/main/java/de/ypchat/android/ui/YpChatRoot.kt b/android/app/src/main/java/de/ypchat/android/ui/YpChatRoot.kt index e6a68c8..9bde658 100644 --- a/android/app/src/main/java/de/ypchat/android/ui/YpChatRoot.kt +++ b/android/app/src/main/java/de/ypchat/android/ui/YpChatRoot.kt @@ -1,5 +1,10 @@ package de.ypchat.android.ui +import android.Manifest +import android.content.Context +import android.content.pm.PackageManager +import android.graphics.Bitmap +import android.net.Uri import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.PickVisualMediaRequest import androidx.activity.result.contract.ActivityResultContracts @@ -76,6 +81,8 @@ import java.time.Instant import java.time.ZoneId import java.time.format.DateTimeFormatter import java.time.format.FormatStyle +import java.io.File +import java.io.FileOutputStream enum class AppTab(val labelRes: Int) { Online(R.string.tab_online), @@ -87,7 +94,7 @@ enum class AppTab(val labelRes: Int) { } private enum class MoreSection { - Overview, Feedback, Partners, Faq, Rules, Safety, Imprint + Overview, Feedback, Partners, Faq, Rules, Safety, Privacy, Imprint } private val BgApp = Color(0xFFF4F6F5) @@ -105,6 +112,7 @@ private val Primary600 = Color(0xFF2F6F46) private val Primary500 = Color(0xFF3D8654) private val Primary100 = Color(0xFFE7F1EA) private val Danger = Color(0xFFA24040) +private const val PrivacyPolicyUrl = "https://www.single-chat.net/datenschutz" private data class GenderOption(val value: String, val label: String) private data class SmileyItem(val token: String, val hexCode: String, val tooltip: String) @@ -574,6 +582,7 @@ private fun MoreScreen(state: ChatState, viewModel: ChatViewModel, section: More MoreSection.Faq -> StaticContentScreen(stringResource(R.string.faq_title), stringResource(R.string.faq_body)) { onSectionChange(MoreSection.Overview) } MoreSection.Rules -> StaticContentScreen(stringResource(R.string.rules_title), stringResource(R.string.rules_body)) { onSectionChange(MoreSection.Overview) } MoreSection.Safety -> StaticContentScreen(stringResource(R.string.safety_title), stringResource(R.string.safety_body)) { onSectionChange(MoreSection.Overview) } + MoreSection.Privacy -> PrivacyScreen { onSectionChange(MoreSection.Overview) } MoreSection.Imprint -> StaticContentScreen(stringResource(R.string.imprint_title), stringResource(R.string.imprint_body)) { onSectionChange(MoreSection.Overview) } } } @@ -587,6 +596,7 @@ private fun MoreOverviewScreen(onSectionChange: (MoreSection) -> Unit) { item { MoreLinkCard(stringResource(R.string.more_faq), stringResource(R.string.faq_intro)) { onSectionChange(MoreSection.Faq) } } item { MoreLinkCard(stringResource(R.string.more_rules), stringResource(R.string.rules_intro)) { onSectionChange(MoreSection.Rules) } } item { MoreLinkCard(stringResource(R.string.more_safety), stringResource(R.string.safety_intro)) { onSectionChange(MoreSection.Safety) } } + item { MoreLinkCard(stringResource(R.string.more_privacy), stringResource(R.string.privacy_intro)) { onSectionChange(MoreSection.Privacy) } } item { MoreLinkCard(stringResource(R.string.more_imprint), stringResource(R.string.imprint_intro)) { onSectionChange(MoreSection.Imprint) } } } } @@ -712,6 +722,29 @@ private fun PartnersScreen(links: List, error: String?, onBack: } } +@Composable +private fun PrivacyScreen(onBack: () -> Unit) { + val uriHandler = LocalUriHandler.current + + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + BackHeader(stringResource(R.string.privacy_title), onBack) + Text(stringResource(R.string.privacy_body), color = TextStrong) + Button( + onClick = { uriHandler.openUri(PrivacyPolicyUrl) }, + colors = ButtonDefaults.buttonColors(containerColor = Primary600), + modifier = Modifier.fillMaxWidth() + ) { + Text(stringResource(R.string.privacy_open_policy)) + } + } +} + @Composable private fun StaticContentScreen(title: String, body: String, onBack: () -> Unit) { Column( @@ -743,6 +776,25 @@ private fun ChatScreen(state: ChatState, viewModel: ChatViewModel) { val imagePicker = rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> if (uri != null) viewModel.sendImage(context, uri) } + val cameraLauncher = rememberLauncherForActivityResult(ActivityResultContracts.TakePicturePreview()) { bitmap -> + if (bitmap != null) { + val uri = saveCameraBitmap(context, bitmap) + if (uri != null) { + viewModel.sendImage(context, uri) + } else { + viewModel.setImageUploadMessage("Camera capture failed") + } + } else { + viewModel.setImageUploadMessage("Camera capture failed") + } + } + val cameraPermissionLauncher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { granted -> + if (granted) { + cameraLauncher.launch(null) + } else { + viewModel.setImageUploadMessage("Camera permission denied") + } + } Column(modifier = Modifier.fillMaxSize()) { Row(modifier = Modifier.fillMaxWidth().padding(12.dp), verticalAlignment = Alignment.CenterVertically) { @@ -782,6 +834,25 @@ private fun ChatScreen(state: ChatState, viewModel: ChatViewModel) { enabled = !state.isUploadingImage ) Spacer(Modifier.width(8.dp)) + TextButton( + onClick = { + if (context.checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { + cameraLauncher.launch(null) + } else { + cameraPermissionLauncher.launch(Manifest.permission.CAMERA) + } + }, + enabled = !state.isUploadingImage, + colors = ButtonDefaults.textButtonColors( + containerColor = Primary100, + contentColor = Primary700, + disabledContainerColor = SurfaceSubtle, + disabledContentColor = TextMuted + ) + ) { + Text(stringResource(R.string.button_camera), fontWeight = FontWeight.Bold) + } + Spacer(Modifier.width(8.dp)) Button( onClick = { viewModel.sendMessage(draft); draft = "" }, colors = ButtonDefaults.buttonColors(containerColor = Primary600), @@ -813,6 +884,16 @@ private fun ChatScreen(state: ChatState, viewModel: ChatViewModel) { } } +private fun saveCameraBitmap(context: Context, bitmap: Bitmap): Uri? { + return runCatching { + val file = File(context.cacheDir, "singlechat-photo-${System.currentTimeMillis()}.jpg") + FileOutputStream(file).use { output -> + bitmap.compress(Bitmap.CompressFormat.JPEG, 88, output) + } + Uri.fromFile(file) + }.getOrNull() +} + @Composable private fun UploadStatusBanner(state: ChatState) { val message = when { @@ -1007,6 +1088,10 @@ private fun localizeRuntimeMessage(message: String): String { stringResource(R.string.image_upload_too_large) message == "Image could not be opened" -> stringResource(R.string.image_upload_open_failed) + message == "Camera permission denied" -> + stringResource(R.string.camera_permission_denied) + message == "Camera capture failed" -> + stringResource(R.string.camera_capture_failed) message.endsWith(" blocked") -> stringResource(R.string.user_blocked, message.removeSuffix(" blocked")) message.endsWith(" unblocked") -> diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..d84c8fb Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..49324e6 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..16e9956 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..45ee1cb Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..bca1439 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values-de/strings.generated.xml b/android/app/src/main/res/values-de/strings.generated.xml deleted file mode 100644 index 06d1672..0000000 --- a/android/app/src/main/res/values-de/strings.generated.xml +++ /dev/null @@ -1,29 +0,0 @@ - - Bitte gib deinen Nicknamen für den Chat ein: - Geschlecht: - Alter: - Land: - Chat starten - Weiblich - Männlich - Paar - Transgender (M->F) - Transgender (F->M) - Suchen - Posteingang - Verlauf - Senden - Benutzername enthält - Von Alter - Bis Alter - Land - Geschlechter - Alle - Suchen - Keine Ergebnisse. - Das Mindestalter muss mindestens so groß sein wie das Höchstalter. - Keine vorherigen Unterhaltungen verfügbar. - Benutzer blockieren - Benutzer entsperren - Ein Bild senden - diff --git a/android/app/src/main/res/values-de/strings.xml b/android/app/src/main/res/values-de/strings.xml index 1aa2440..b0bd3e5 100644 --- a/android/app/src/main/res/values-de/strings.xml +++ b/android/app/src/main/res/values-de/strings.xml @@ -49,6 +49,7 @@ Entsperren Nachricht Bild + Foto Senden Smileys Bildnachricht @@ -57,6 +58,8 @@ Bild-Upload fehlgeschlagen. Das Bild ist größer als 5 MB. Das Bild konnte nicht geöffnet werden. + Die Kameraberechtigung wurde abgelehnt. + Das Foto konnte nicht aufgenommen werden. Eingegangen %1$s Länderliste konnte nicht geladen werden: %1$s @@ -83,21 +86,26 @@ FAQ Regeln Sicherheit + Datenschutz Impressum Zur Übersicht Empfehlungen und befreundete Projekte für unsere Community. Antworten auf häufige Fragen zum Chat. Grundregeln für respektvollen Chat. Tipps für Privatsphäre und sichere Nutzung. + Datenschutzerklärung, verarbeitete Daten und Kontakt für Datenschutzanfragen. Rechtliche Hinweise und Kontaktdaten. Externer Link Häufige Fragen Chat-Regeln Sicherheit und Privatsphäre + Datenschutzerklärung Impressum Partner Wähle einen Nicknamen, gib deine Profildaten an und starte den Chat. Teile keine sensiblen Daten wie Telefonnummern, Adressen, Passwörter oder Zahlungsinformationen. Du kannst Bilder senden, Benutzer blockieren und Feedback für ernste Vorfälle nutzen. Keine Beleidigungen, Hassrede, illegalen Inhalte, Spam oder unerwünschte Belästigung. Sende nur Bilder, die du teilen darfst, und respektiere die Privatsphäre anderer. Nutze einen Nicknamen, der dich nicht identifiziert. Teile keine privaten Kontakt- oder Zahlungsdaten. Sei vorsichtig mit Links von Unbekannten und beende Gespräche, die sich falsch anfühlen. Nutze Blockieren und Feedback bei schweren Vorfällen. + SingleChat verarbeitet den von dir gewählten Nickname, Profildaten wie Alter, Geschlecht und Land, Chat-Nachrichten, von dir aktiv gesendete Bilder, Feedback-Nachrichten sowie technisch notwendige Sitzungsdaten. Die Android-App fragt den Kamerazugriff nur an, wenn du in der App aktiv ein Foto aufnehmen möchtest. Die vollständige Datenschutzerklärung für Website und App ist auf single-chat.net veröffentlicht. + Datenschutzerklärung öffnen Torsten Schulz, Friedrich-Stampfer-Str. 21, 60437 Frankfurt. Kontakt: tsschulz@tsschulz.de. Für externe Links sind deren Betreiber verantwortlich. diff --git a/android/app/src/main/res/values-es/strings.generated.xml b/android/app/src/main/res/values-es/strings.generated.xml deleted file mode 100644 index c5bdb3e..0000000 --- a/android/app/src/main/res/values-es/strings.generated.xml +++ /dev/null @@ -1,29 +0,0 @@ - - Por favor, escribe tu apodo para el chat: - Género: - Edad: - País: - Iniciar chat - Femenino - Masculino - Pareja - Transgénero (M->F) - Transgénero (F->M) - Buscar - Bandeja de entrada - Historial - Enviar - El nombre de usuario incluye - Desde la edad - Hasta la edad - País - Géneros - Todos - Buscar - Sin resultados. - La edad mínima debe ser al menos tan grande como la edad máxima. - No hay conversaciones anteriores disponibles. - Bloquear usuario - Desbloquear usuario - Enviar una imagen - diff --git a/android/app/src/main/res/values-fr/strings.generated.xml b/android/app/src/main/res/values-fr/strings.generated.xml deleted file mode 100644 index fa53618..0000000 --- a/android/app/src/main/res/values-fr/strings.generated.xml +++ /dev/null @@ -1,29 +0,0 @@ - - Veuillez saisir votre pseudo pour le chat: - Genre: - Âge: - Pays: - Démarrer le chat - Féminin - Masculin - Couple - Transgenre (M->F) - Transgenre (F->M) - Rechercher - Boîte de réception - Historique - Envoyer - Le nom d\'utilisateur contient - À partir de l\'âge - Jusqu\'à l\'âge - Pays - Genres - Tous - Rechercher - Aucun résultat. - L\'âge minimum doit être au moins aussi grand que l\'âge maximum. - Aucune conversation précédente disponible. - Bloquer l\'utilisateur - Débloquer l\'utilisateur - Envoyer une image - diff --git a/android/app/src/main/res/values-it/strings.generated.xml b/android/app/src/main/res/values-it/strings.generated.xml deleted file mode 100644 index f996222..0000000 --- a/android/app/src/main/res/values-it/strings.generated.xml +++ /dev/null @@ -1,29 +0,0 @@ - - Inserisci il tuo nickname per la chat: - Genere: - Età: - Paese: - Inizia chat - Femmina - Maschio - Coppia - Transgender (M->F) - Transgender (F->M) - Cerca - Posta in arrivo - Cronologia - Invia - Il nome utente include - Dall\'età - Fino all\'età - Paese - Generi - Tutti - Cerca - Nessun risultato. - L\'età minima deve essere almeno grande quanto l\'età massima. - Nessuna conversazione precedente disponibile. - Blocca utente - Sblocca utente - Invia un\'immagine - diff --git a/android/app/src/main/res/values-ja/strings.generated.xml b/android/app/src/main/res/values-ja/strings.generated.xml deleted file mode 100644 index a297ff1..0000000 --- a/android/app/src/main/res/values-ja/strings.generated.xml +++ /dev/null @@ -1,29 +0,0 @@ - - チャット用のニックネームを入力してください: - 性別: - 年齢: - 国: - チャットを開始 - 女性 - 男性 - カップル - トランスジェンダー (M->F) - トランスジェンダー (F->M) - 検索 - 受信トレイ - 履歴 - 送信 - ユーザー名に含まれる - 年齢から - 年齢まで - - 性別 - すべて - 検索 - 結果がありません。 - 最小年齢は最大年齢以上でなければなりません。 - 以前の会話はありません。 - ユーザーをブロック - ユーザーのブロックを解除 - 画像を送信 - diff --git a/android/app/src/main/res/values-th/strings.generated.xml b/android/app/src/main/res/values-th/strings.generated.xml deleted file mode 100644 index ce1e657..0000000 --- a/android/app/src/main/res/values-th/strings.generated.xml +++ /dev/null @@ -1,29 +0,0 @@ - - กรุณาพิมพ์ชื่อเล่นของคุณสำหรับแชท: - เพศ: - อายุ: - ประเทศ: - เริ่มแชท - หญิง - ชาย - คู่ - ทรานส์เจนเดอร์ (M->F) - ทรานส์เจนเดอร์ (F->M) - ค้นหา - กล่องจดหมาย - ประวัติ - ส่ง - ชื่อผู้ใช้รวมถึง - จากอายุ - ถึงอายุ - ประเทศ - เพศ - ทั้งหมด - ค้นหา - ไม่มีผลลัพธ์ - อายุขั้นต่ำต้องมากกว่าหรือเท่ากับอายุสูงสุด - ไม่มีการสนทนาก่อนหน้านี้ - บล็อกผู้ใช้ - ยกเลิกการบล็อกผู้ใช้ - ส่งรูปภาพ - diff --git a/android/app/src/main/res/values-tl/strings.generated.xml b/android/app/src/main/res/values-tl/strings.generated.xml deleted file mode 100644 index b2ed9a7..0000000 --- a/android/app/src/main/res/values-tl/strings.generated.xml +++ /dev/null @@ -1,29 +0,0 @@ - - Mangyaring i-type ang iyong nickname para sa chat: - Kasarian: - Edad: - Bansa: - Simulan ang chat - Babae - Lalaki - Mag-asawa - Transgender (M->F) - Transgender (F->M) - Maghanap - Inbox - Kasaysayan - Ipadala - Kasama sa username - Mula sa edad - Hanggang edad - Bansa - Kasarian - Lahat - Maghanap - Walang resulta. - Ang minimum na edad ay dapat na hindi bababa sa maximum na edad. - Walang nakaraang pag-uusap na available. - I-block ang user - I-unblock ang user - Magpadala ng larawan - diff --git a/android/app/src/main/res/values-zh-rCN/strings.generated.xml b/android/app/src/main/res/values-zh-rCN/strings.generated.xml deleted file mode 100644 index d7ef332..0000000 --- a/android/app/src/main/res/values-zh-rCN/strings.generated.xml +++ /dev/null @@ -1,29 +0,0 @@ - - 请输入您的聊天昵称: - 性别: - 年龄: - 国家: - 开始聊天 - 女性 - 男性 - 情侣 - 跨性别 (M->F) - 跨性别 (F->M) - 搜索 - 收件箱 - 历史记录 - 发送 - 用户名包含 - 从年龄 - 到年龄 - 国家 - 性别 - 全部 - 搜索 - 没有结果。 - 最小年龄必须至少等于或大于最大年龄。 - 没有可用的历史对话。 - 屏蔽用户 - 取消屏蔽用户 - 发送图片 - diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index e564ad9..e769f0a 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -49,6 +49,7 @@ Unblock Message Image + Photo Send Smileys Image message @@ -57,6 +58,8 @@ Image upload failed. Image is larger than 5 MB. Image could not be opened. + Camera permission was denied. + Photo could not be captured. Received %1$s Country list could not be loaded: %1$s @@ -83,21 +86,26 @@ FAQ Rules Safety + Privacy Imprint Back to overview Recommended and friendly projects for our community. Answers to common questions about the chat. Basic rules for respectful chatting. Tips for privacy and safer usage. + Privacy policy, processed data and contact for privacy requests. Legal notice and contact details. External link Frequently Asked Questions Chat Rules Safety and Privacy + Privacy Policy Imprint Partners Choose a nickname, enter your profile details and start chatting. Do not share sensitive data like phone numbers, addresses, passwords or payment information. You can send images, block users and use feedback for serious issues. No insults, hate speech, illegal content, spam or unwanted harassment. Only send images you are allowed to share and respect the privacy of others. Use a nickname that does not identify you. Do not share private contact or payment data. Be careful with links from strangers and end conversations that feel wrong. Use block and feedback for serious incidents. + SingleChat processes the nickname you choose, profile details such as age, gender and country, chat messages, images you actively send, feedback messages and technically necessary session data. The Android app requests camera access only if you actively want to take a photo in the app. The full privacy policy for website and app is published on single-chat.net. + Open privacy policy Torsten Schulz, Friedrich-Stampfer-Str. 21, 60437 Frankfurt. Contact: tsschulz@tsschulz.de. External links are the responsibility of their operators. diff --git a/client/src/components/ChatInput.vue b/client/src/components/ChatInput.vue index b450f95..8ff7255 100644 --- a/client/src/components/ChatInput.vue +++ b/client/src/components/ChatInput.vue @@ -25,6 +25,15 @@ > Image +
+ +
+
+
+

Foto aufnehmen

+ +
+ +
+ {{ cameraError }} +
+ +
+ + Aufgenommenes Foto +
+ Kamera wird gestartet ... +
+
+ + + +
+ + + +
+
+
+ diff --git a/client/src/views/PrivacyView.vue b/client/src/views/PrivacyView.vue index 421fc7e..09d9ea3 100644 --- a/client/src/views/PrivacyView.vue +++ b/client/src/views/PrivacyView.vue @@ -17,6 +17,11 @@ Diese Datenschutzerklärung gilt für die Website und die Android-App von SingleChat unter der Domain www.single-chat.net.

+

+ Sie beschreibt die Verarbeitung personenbezogener Daten im Zusammenhang mit der Nutzung der + Chat-Funktionen, der Bildfreigabe, von Feedback-Meldungen und der technisch notwendigen + Sitzungsverwaltung. +

1. Verantwortlicher

@@ -48,59 +53,88 @@

  • Bearbeitung von Feedback und Missbrauchshinweisen
  • -

    4. Chat-Nachrichten und Profilangaben

    +

    4. Rechtsgrundlagen

    +

    + Soweit personenbezogene Daten verarbeitet werden, erfolgt dies in der Regel zur Erfüllung + der angeforderten Chat-Funktionen und auf Grundlage berechtigter Interessen an einem + sicheren, stabilen und missbrauchsarmen Betrieb des Angebots. +

    + +

    5. Chat-Nachrichten und Profilangaben

    Wenn du den Dienst nutzt, werden von dir eingegebene Profilangaben wie Nickname, Alter, Geschlecht und Land für die Chat-Funktion verwendet. Chat-Nachrichten werden technisch verarbeitet, damit Unterhaltungen in Echtzeit zugestellt werden können.

    -

    5. Bilder

    +

    6. Bilder und Kamerazugriff

    Bilder werden nur verarbeitet, wenn du sie aktiv auswählst und hochlädst. Nach aktuellem Systemstand werden hochgeladene Bilder serverseitig temporär gespeichert und nach Ablauf einer begrenzten Zeit wieder entfernt.

    +

    + Die Android-App fordert die Kameraberechtigung nur an, wenn du in der App aktiv ein Foto aufnehmen möchtest. + Ohne deine Auslösung erfolgt kein Kamerazugriff. +

    -

    6. Sitzungen, Cookies und technische Protokolle

    +

    7. Sitzungen, Cookies und technische Protokolle

    Für den Betrieb des Dienstes werden Sitzungsdaten verwendet. Dazu gehören insbesondere technisch notwendige Session-Informationen, damit ein Login erhalten bleibt und Socket- sowie API-Anfragen korrekt zugeordnet werden können. Zusätzlich können im Rahmen des Serverbetriebs technische Protokolldaten anfallen.

    -

    7. Feedback und Missbrauchsmeldungen

    +

    8. Feedback und Missbrauchsmeldungen

    Wenn du Feedback sendest, werden die von dir eingetragenen Inhalte verarbeitet, um Hinweise, Fehlermeldungen oder Missbrauchsmeldungen zu bearbeiten.

    -

    8. Weitergabe an Dritte

    +

    9. Weitergabe an Dritte

    Eine Weitergabe personenbezogener Daten an Dritte erfolgt nicht zu Werbezwecken. Soweit externe technische Dienstleister oder Hosting-Anbieter eingebunden sind, kann eine Verarbeitung im Rahmen des technischen Betriebs erforderlich sein.

    -

    9. Verschlüsselung

    +

    10. Werbung, Standort und weitere sensible Daten

    +

    + Die Android-App verwendet nach aktuellem Stand kein Werbe-SDK und verarbeitet keine Standortdaten, Kontaktlisten, + Gesundheitsdaten oder Zahlungsdaten. Solche Daten werden weder angefordert noch fuer die Kernfunktion des Chats + benoetigt. +

    + +

    11. Verschlüsselung

    Die produktive Bereitstellung der Website und der App erfolgt über verschlüsselte Verbindungen, damit Daten bei der Übertragung geschützt sind.

    -

    10. Deine Rechte

    +

    12. Speicherdauer

    +

    + Personenbezogene Daten werden nicht länger gespeichert, als es für den technischen Betrieb, die Bereitstellung der + Funktionen und die Bearbeitung von Missbrauchs- oder Supportanfragen erforderlich ist. Bilder sind für eine + begrenzte Verfügbarkeit im Chat gedacht und werden nicht dauerhaft als öffentliches Archiv bereitgestellt. +

    + +

    13. Deine Rechte

    Du hast im Rahmen der gesetzlichen Vorschriften insbesondere das Recht auf Auskunft, Berichtigung, Löschung, Einschränkung der Verarbeitung sowie Beschwerde bei einer zuständigen Aufsichtsbehörde.

    -

    11. Kontakt zum Datenschutz

    +

    14. Kontakt zum Datenschutz

    Bei Fragen zum Datenschutz oder wenn du eine datenschutzbezogene Anfrage stellen möchtest, kontaktiere bitte: tsschulz@tsschulz.de.

    +

    + Wenn du die Löschung von Daten anfragen möchtest, teile bitte den verwendeten Nickname, den ungefähren Zeitraum der + Nutzung und - soweit vorhanden - weitere zur Zuordnung notwendige Angaben mit. +

    -

    12. Stand

    -

    Stand dieser Datenschutzerklärung: 22. April 2026

    +

    15. Stand

    +

    Stand dieser Datenschutzerklärung: 16. Juni 2026