implement legal dialog in english

This commit is contained in:
vd
2026-10-12 22:51:11 +02:00
parent ab1cfbd308
commit 4956e26af9
6 changed files with 141 additions and 2 deletions
+87
View File
@@ -0,0 +1,87 @@
import { SplitModal } from "./splitModal";
import { languageNames } from "../translations";
import { CommonKeys, getKeySymbol } from "../keystrokes";
import { PlaceholderView } from "../Components/placeholderView";
import { OptionButtonList } from "../Components/optionButtonList";
import { NavigationButton } from "../Components/navigationButton";
import { InfoTile } from "../Components/infoTile";
import * as React from "../../react";
import SettingsViewModel, {
SettingsModalPages,
} from "../../ViewModel/Global/settingsViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import { Languages, ThemeSettings } from "../../Model/Global/settingsModel";
import HomeViewModel from "../../ViewModel/Pages/homeViewModel";
export function LegalModal(
coreViewModel: CoreViewModel,
homeViewModel: HomeViewModel,
) {
return (
<div
class="modal"
toggle:open={homeViewModel.isPresentingLegalModal}
>
<div>
<main>
<h1>{coreViewModel.translations.legal.legalHeadline}</h1>
<p class="secondary">{coreViewModel.translations.legal.legalDescription}</p>
<hr></hr>
<div class="flex-column gap">
<div class="tile">
<span class="icon">privacy_tip</span>
<div>
<b>{coreViewModel.translations.legal.privacyLabel}</b>
<span class="secondary">{coreViewModel.translations.legal.privacyDescription}</span>
</div>
</div>
<div class="tile">
<span class="icon">cell_tower</span>
<div>
<b>{coreViewModel.translations.legal.udnLabel}</b>
<span class="secondary">{coreViewModel.translations.legal.udnDescription}</span>
</div>
</div>
<div class="tile">
<span class="icon">balance</span>
<div>
<b>{coreViewModel.translations.legal.rightsLabel}</b>
<span class="secondary">{coreViewModel.translations.legal.rightsDescription}</span>
</div>
</div>
<hr></hr>
<button
class="tile"
on:click={coreViewModel.openImprint}
>
<span class="icon">contact_page</span>
<div>
<b>{coreViewModel.translations.legal.imprintLabel}</b>
<span class="secondary">{coreViewModel.translations.legal.imprintDescription}</span>
</div>
<span class="icon">open_in_new</span>
</button>
<button
class="tile"
on:click={coreViewModel.openProviderContact}
>
<span class="icon">domain</span>
<div>
<b>{coreViewModel.translations.legal.infrastructureLabel}</b>
<span class="secondary">{coreViewModel.translations.legal.infrastructureDescription}</span>
</div>
<span class="icon">open_in_new</span>
</button>
</div>
</main>
<button
on:click={homeViewModel.closeLegalModal}
ctkeystroke={getKeySymbol(CommonKeys.CloseOrCancel)}
>
{coreViewModel.translations.general.closeButton}
<span class="icon">close</span>
</button>
</div>
</div>
);
}
+8
View File
@@ -10,9 +10,11 @@ import FileTransferViewModel from "../ViewModel/Global/fileTransferViewModel";
import CoreViewModel from "../ViewModel/Global/coreViewModel";
import ConnectionViewModel from "../ViewModel/Global/connectionViewModel";
import ChatListViewModel from "../ViewModel/Chat/chatListViewModel";
import HomeViewModel from "../ViewModel/Pages/homeViewModel";
export function HomePage(
coreViewModel: CoreViewModel,
homeViewModel: HomeViewModel,
storageViewModel: StorageViewModel,
settingsViewModel: SettingsViewModel,
connectionViewModel: ConnectionViewModel,
@@ -119,6 +121,12 @@ export function HomePage(
"hard_drive",
"e",
)}
{HomePageButton(
homeViewModel.openLegalModal,
coreViewModel.translations.homePage.legalButton,
"gavel",
"i",
)}
<button
class="primary"
+21
View File
@@ -69,6 +69,7 @@ const englishTranslations = {
settingsButton: "Settings",
manageStorageButton: "Manage storage",
transferDataButton: "Transfer or export data",
legalButton: "Legal information",
updateButton: (version: string) => `Update to ${version}`,
@@ -109,6 +110,26 @@ const englishTranslations = {
},
},
legal: {
legalHeadline: "Legal Information",
legalDescription: "CT is open source software published and distributed under the GPL-3.0 license.",
privacyLabel: "Privacy and Application Data",
privacyDescription: "CT stores data on your device. No data is stored on the server hosting this instance of CT, except for session data necessary to provide a website. This data is handled and processed by the infrastructure provider (data processor).",
udnLabel: "UDN Servers and Communications",
udnDescription: "The UDN servers you connect to are separate and independent from CT. When connected to a server, chats you create and the entities contained therein, including but not limited to messages, boards, and tasks, are transferred to the respective UDN server. Confer the privacy policy of this server for more information.",
imprintLabel: "Imprint",
imprintDescription: "Contact information of the data controller (operator) providing this instance of CT",
infrastructureLabel: "Infrastructure",
infrastructureDescription: "Contact information of the data processor (provider) hosting this instance of CT on behalf of the operator",
rightsLabel: "Your Rights",
rightsDescription: "You have the right to object to any processing of your data, and to request access, changes, and deletion to/of your data by contacting the operator and/or processor. Note that this right may not be applicable if data is not being processed for purposes other than provision of CT. You have the right to lodge a complaint with a data protection supervisory authority, free of charge and without any formal requirements, if you believe the processing of your personal data infringes the GDPR.",
},
onboarding: {
connectionHeadline: "Connect to UDN",
connectionDescription:
+8
View File
@@ -158,6 +158,14 @@ export default class CoreViewModel {
window.open("https://vdpr.org/VDMDI/CT");
}
openImprint = (): void => {
window.open("/imprint");
}
openProviderContact = (): void => {
window.open("/provider");
}
// init
constructor(
public readonly storageModel: StorageModel,
+12
View File
@@ -7,6 +7,16 @@ import * as React from "../../react";
import { CommonKeys } from "../../View/keystrokes";
export default class HomeViewModel extends Context {
isPresentingLegalModal: React.State<boolean> = new React.State<boolean>(false);
openLegalModal = (): void => {
this.isPresentingLegalModal.value = true;
}
closeLegalModal = (): void => {
this.isPresentingLegalModal.value = false;
}
constructor(
public readonly coreViewModel: CoreViewModel,
public readonly settingsViewModel: SettingsViewModel,
@@ -26,6 +36,8 @@ export default class HomeViewModel extends Context {
"t",
this.fileTransferViewModel.showDirectionSelectionModal,
);
this.registerKeyStroke("i", this.openLegalModal);
this.registerKeyStroke(CommonKeys.CloseOrCancel, this.closeLegalModal);
this.registerKeyStroke("e", this.storageViewModel.showStorageModal);
this.registerKeyStroke("x", this.connectionViewModel.disconnect);
this.registerKeyStroke("c", this.connectionViewModel.connect);
+5 -2
View File
@@ -24,6 +24,7 @@ import FileTransferModel from "./Model/Global/fileTransferModel";
import ContactListModel from "./Model/Global/contactListModel";
import ConnectionModel from "./Model/Global/connectionModel";
import ChatListModel from "./Model/Chat/chatListModel";
import {LegalModal} from "./View/Modals/legalModal";
// models
const storageModel = new StorageModel();
@@ -97,7 +98,8 @@ document
.querySelector("main")!
.append(
HomePage(
coreViewModel,
coreViewModel,
homeViewModel,
storageViewModel,
settingsViewModel,
connectionViewModel,
@@ -106,6 +108,7 @@ document
),
ChatPageWrapper(coreViewModel, chatListViewModel),
OnboardingModalWrapper(coreViewModel, onboardingViewModel),
LegalModal(coreViewModel, homeViewModel),
ConnectionModal(coreViewModel, connectionViewModel),
DataTransferModalWrapper(
coreViewModel,
@@ -113,5 +116,5 @@ document
fileTransferViewModel,
),
StorageModal(coreViewModel, storageViewModel),
SettingsModal(coreViewModel, settingsViewModel),
SettingsModal(coreViewModel, settingsViewModel),
);