first commit

This commit is contained in:
om 2022-09-22 08:35:37 +02:00
commit 5bba2c2bf9
4 changed files with 826 additions and 0 deletions

41
da/index.html Normal file
View file

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ChatControl: Dine private beskeder skal overvågnes!</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" type="text/css" href="../style.css" />
</head>
<body>
<h1><span class="besked">ChatControl: Dine private beskeder skal overvågnes</span></h1>
<p>
EU-kommissionen har lavet et nyt lovforslag for at beskytte børn mod misbrug.
Formålet er godt, men loven er dårligt, fordi det kræver at tjenester
som tilbyder kommunikation skal overvågnes hvis der er en mulighed for at børn
bruger dem eller hvis der er en mulighed for at dele billeder af børnemisbrug.
Det vil påvirke mange kommunikationstjenste og vil betyde at din kommunikation
vil blive overvågnet, fordi alle brugere af almindelige kommunikationstjenste
vil være mistænkt for at begår børnemisbrug.
</p>
<div id="app-area">
<object id="movie" data="../img/chatapp.svg" type="image/svg+xml"></object>
<p id="movie-sidetext">
Lær mere om ChatControllen og hvorfor det er en dårlig idé i vores interaktivt
ChatControl film til venstre side.
</p>
</div>
<p>
Hvad kan man så gøre imod lovforslaget? Det er vigtigt at mere folk lær om det.
Så del linket til denne side! Snak med andre om det og tale med
<a href="https://www.europarl.europa.eu/meps/da/full-list">dine politikere i europaparlamentet</a>
om det (eller skriv en venlig e-mail til dem).
Det er vigtigt at der er en offentlig diskussion om emnet og at politikere ved
at loven er en meget dårlig idé selvom formålet er godt.
</p>
</body>
</html>

737
img/chatapp.svg Normal file
View file

@ -0,0 +1,737 @@
<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="300"
height="600"
viewBox="0 0 300 600"
onload="start_chat('Ven')"
overflow="auto"
style="font-family: sans; border-radius: 10px;"
>
<defs>
<symbol id="kaereste_foto" width="60" height="200">
<g style="fill: pink; stroke: pink;">
<circle cx="20" cy="20" r="20" />
<line x1="20" y1="40" x2="20" y2="60" />
<ellipse cx="20" cy="110" rx="10" ry="50" />
<!-- left arm -->
<polyline fill="none"
points="15,70 5,50 0,40" />
<!-- right arm -->
<polyline fill="none"
points="25,70 35,50 40,40" />
<!-- left leg -->
<polyline fill="none"
points="15,155 5,135 0,125" />
<!-- right leg -->
<polyline fill="none"
points="25,155 35,135 40,125" />
<!-- the thing -->
<text x="14" y="160" style="font: bold 20px sans-serif" fill="black">?</text>
</g>
</symbol>
<symbol id="flag_denmark" width="20" height="15">
<path fill="#c8102e" d="M0,0H20V15H0Z"/>
<path fill="#fff" d="M0,6H6V0H8V6H20V8H8V15H6V8H0Z"/>
</symbol>
<symbol id="flag_uk" width="50" height="30">
<clipPath id="t">
<path d="M25,15h25v15zv15h-25zh-25v-15zv-15h25z"/>
</clipPath>
<path d="M0,0v30h50v-30z" fill="#012169"/>
<path d="M0,0 50,30M50,0 0,30" stroke="#fff" stroke-width="6"/>
<path d="M0,0 50,30M50,0 0,30" clip-path="url(#t)" stroke="#C8102E" stroke-width="4"/>
<path d="M-1 11h22v-12h8v12h22v8h-22v12h-8v-12h-22z" fill="#C8102E" stroke="#FFF" stroke-width="2"/>
</symbol>
</defs>
<script type="application/ecmascript">
<![CDATA[
'use strict';
const svgns = "http://www.w3.org/2000/svg";
// must be the same as the SVG dimensions
const width = 300;
const height = 550;
const line_height = 14;
const bubble_padding = 6;
const bubble_spacing = 5;
const visible_chat_area = {'top': 60,
'bottom': height - 100 // minus status & input areas
};
const typing_speed = 50;
var conversation_count = 0;
var current_dialog = null;
var current_language = "da";
var current_dialog_fn = null;
/// SVG 1.1 doesn't do proper text splitting into several lines.
/// we need to do it ourselves.
function split_text_into_lines(text, upper_line_length) {
let result = [];
while(text.length) {
if(text.length < upper_line_length) {
result.push(text);
break; // we are done
}
let found_split_point = false;
for(let i = upper_line_length; i; i--) {
if(text[i] == ' ') {
result.push(text.slice(0, i));
text = text.slice(i+1);
found_split_point = true;
break;
}
}
if(!found_split_point) {
// no <space> found. Split at character boundary instead
result.push(text.slice(0, upper_line_length));
text = text.slice(upper_line_length);
}
}
return result;
}
function is_hyperlink(str) {
return str.startsWith('http');
}
function create_link_node(url) {
let link = create_svg_node('a', {target:'_blank', href: url});
link.appendChild(document.createTextNode(url));
return link;
}
/// A class holding a text chat message.
///
/// *ChatMessages are owned by a Dialog.
function TextChatMessage(message_text, is_myself) {
let lines = split_text_into_lines(message_text, 28);
let bubble_color = (is_myself)? '#0084FF': '#E4E6EB';
let text_color = (is_myself)? 'white': 'black';
let container = document.getElementById('messages');
// attributes
this.height = 0; // height on screen when fully visible
this.group = null; // a <g> with a transform=translate(0,y_shift) attribute
/// Render the chat message on the screen
this.draw = function(y_offset, y_shift) {
let group = create_svg_node('g', {'transform': `translate(0, ${y_shift})`});
let x = (is_myself ? 195 : 105);
let text = create_svg_node('text', {
'x': `${x}%`,
'font-size': `${line_height}px`,
'text-anchor': is_myself ? 'end' : 'start'
});
let height_so_far = y_offset;
lines.forEach(function(line) {
let y = height_so_far;
let tspan = create_svg_node('tspan', {
'x': `${x}%`,
'y': `${y + line_height}`, // important: y is lower text baseline
'fill': text_color,
'width': '5%'
});
enable_scrolling(tspan)
if(is_hyperlink(line)) {
tspan.appendChild(create_link_node(line));
} else {
tspan.appendChild(document.createTextNode(line));
}
text.appendChild(tspan);
height_so_far += line_height;
});
group.appendChild(text); // needs to be part of the DOM *now*
container.appendChild(group);
let bubble = create_bubble(text, bubble_color);
group.appendChild(bubble);
redraw_on_top(text);
this.height = bubble.getBBox().height + bubble_spacing;
this.group = group;
}
/// Move a chat message on the screen (to simulate scrolling)
this.shift_y_pos = function(by) {
redraw_on_top(document.getElementById('contact_name_box'));
this.group.setAttribute('transform', `translate(0, ${by})`);
}
}
/// A class holding a image-based chat message.
///
/// *ChatMessages are owned by a Dialog.
function ImageChatMessage(symbol_id, is_myself) {
let container = document.getElementById('messages');
let bubble_color = (is_myself)? 'white': '#DDFF66';
// attributes
this.height = 0; // height on screen when fully visible
this.group = null; // a <g> with a transform=translate(0,y_shift) attribute
this.draw = function(y_offset, y_shift) {
let group = create_svg_node('g', {'transform': `translate(0, ${y_shift})`});
let x = (is_myself ? 190 : 110);
let img = create_svg_node('use', {
'href': symbol_id,
x: `${x}%`,
y: y_offset,
});
group.appendChild(img); // needs to be part of the DOM *now*
container.appendChild(group);
let bubble = create_bubble(img, bubble_color);
group.appendChild(bubble);
redraw_on_top(img);
this.height = bubble.getBBox().height + bubble_spacing;
this.group = group;
}
this.shift_y_pos = function(by) {
redraw_on_top(document.getElementById('contact_name_box'));
this.group.setAttribute('transform', `translate(0, ${by})`);
}
}
function create_chat_message(content, is_myself) {
let constr = (content.startsWith('#'))? ImageChatMessage: TextChatMessage;
return new constr(content, is_myself);
}
/// Promise-based version of setTimeout
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
/// toggle viewport between message list and contact list
/// That means: show either the left or right side of the SVG
function swipe_viewport() {
let svg = document.getElementsByTagName('svg')[0];
let coords = svg.getAttribute('viewBox').split(' ');
let x = parseInt(coords.shift());
if(x == 0) {
// moving from messages to contacts
var step = 5;
var end = width;
} else {
// moving from contacts to messages
var step = -5;
var end = 0;
}
let viewBox_suffix = coords.join(' '); // only 3 elements
async function animate(resolve, reject) {
while(x!=end) {
await wait(1);
x += step;
svg.setAttribute('viewBox', `${x} ${viewBox_suffix}`);
}
resolve();
};
new Promise(animate);
}
// Create a chat bubble around an element.
//
// The element must already be inside the DOM for this to work.
function create_bubble(inner_element, color) {
const bbox = inner_element.getBBox();
let bubble = create_svg_node('rect', {
'x': bbox.x - bubble_padding,
'y': bbox.y - bubble_padding,
'width': bbox.width + 2 * bubble_padding,
'height': bbox.height + 2 * bubble_padding,
'rx': 8,
'fill': color,
});
enable_scrolling(bubble);
return bubble;
}
function create_svg_node(tag_name, attrs) {
let node = document.createElementNS(svgns, tag_name);
for(let attr in attrs) {
node.setAttribute(attr, attrs[attr]);
}
return node;
}
/// Ensure that an element is redrawn above all other elements
///
/// The element's children will also be redrawn on top
function redraw_on_top(element) {
let parent = element.parentNode;
parent.appendChild(parent.removeChild(element));
}
function removeAllChildren(parentNode) {
while(parentNode.firstChild) {
parentNode.removeChild(parentNode.lastChild);
}
}
function start_chat(who) {
let indicator = document.getElementById('contact_indicator');
indicator.childNodes[0].data = `Kontakt: ${who}`;
removeAllChildren(document.getElementById('messages'));
swipe_viewport();
switch(who) {
case 'Ven':
current_dialog_fn = dialog_ven;
break;
case 'Mor':
current_dialog_fn = dialog_mor;
break;
case 'Kæreste':
current_dialog_fn = dialog_kaereste;
break;
case 'Politiven':
current_dialog_fn = dialog_politi;
break;
case 'ChatSupport':
current_dialog_fn = dialog_support;
break;
case 'Nabopige':
current_dialog_fn = dialog_nabopige;
break;
default:
alert(`kontakten ${who} er ikke implementeret endnu`);
return;
}
current_dialog_fn();
}
function Dialog() {
let conversation_id = ++conversation_count;
this.messages = [];
this.y_shift = visible_chat_area.top; // for scrolling
this.all_elements_height = 0; // also for scrolling
this.is_active = function() {
return conversation_id == conversation_count;
}
async function post_message(dialog, message, is_myself) {
if(!is_myself && dialog.messages.length) {
await wait(message.length * typing_speed);
} // first message should be instant
if(!dialog.is_active()) {
return; // Do not add messages to old conversation
}
let chat_message = create_chat_message(message, is_myself);
chat_message.draw(dialog.all_elements_height, // offset
dialog.y_shift);
dialog.all_elements_height += chat_message.height;
dialog.messages.push(chat_message);
let bottom = dialog.all_elements_height + dialog.y_shift;
let scroll = Math.max(0, bottom - visible_chat_area.bottom);
while(scroll > line_height) {
dialog.scroll_by(-line_height);
scroll -= line_height;
await wait(50);
}
}
this.scroll_by = function(change) {
this.y_shift += change;
this.messages.forEach(msg => msg.shift_y_pos(this.y_shift));
}
this.me = async function(message, will_be_flagged) {
await wait(1500); // give me some time to read
if(!this.is_active()) return;
await type_message(this, message);
if(!this.is_active()) return;
hit_send_button();
await local_message_processing(will_be_flagged);
clear_input_field();
release_send_button();
await post_message(this, message, true);
}
this.you = async function(message) {
await post_message(this, message, false);
}
}
async function type_message(dialog, message) {
clear_input_field(); // just to be sure
let text = document.getElementById('message_input_data').firstChild;
let lines = split_text_into_lines(message, 22);
for(let line of lines) {
text.data = '';
for(let c of line) {
await wait(typing_speed);
text.data += c;
}
if(!dialog.is_active()) break;
await wait(20); // otherwise it's too fast
}
}
function hit_send_button() {
document.getElementById('message_submit_button').setAttribute('fill', 'white');
document.getElementById('message_submit_box').setAttribute('fill', '#888888');
}
function release_send_button() {
document.getElementById('message_submit_button').setAttribute('fill', 'black');
document.getElementById('message_submit_box').setAttribute('fill', '#CCCCCC');
}
function clear_input_field() {
let element = document.getElementById('message_input_data')
removeAllChildren(element);
element.appendChild(document.createTextNode(''));
}
async function local_message_processing(will_be_flagged) {
let text_element = document.getElementById('message_status');
let indicator = text_element.childNodes[0];
indicator.data = 'scanning for illegal content';
await wait(800);
if(will_be_flagged) {
let box = document.getElementById('message_status_box');
text_element.setAttribute('fill', 'red');
box.setAttribute('fill', 'yellow');
indicator.data = 'Reporting suspicious content';
await wait(1000);
text_element.setAttribute('fill', 'white');
box.setAttribute('fill', '#FF7B00');
}
indicator.data = 'encrypting message';
await wait(550);
indicator.data = 'sending message';
await wait(500);
indicator.data = 'message was sent';
}
async function scroll_up() {
current_dialog.scroll_by(line_height);
}
async function scroll_down() {
current_dialog.scroll_by(-line_height);
}
const on_wheel = (e) => { e.deltaY < 0 ? scroll_up() : scroll_down() }
const enable_scrolling = (elem) => elem.addEventListener('wheel', on_wheel);
// enable scrolling
document.addEventListener(
"DOMContentLoaded",
() => document.getElementById("message_box").addEventListener('wheel', on_wheel)
)
async function switch_language(language_code) {
current_language = language_code;
removeAllChildren(document.getElementById('messages'));
await current_dialog_fn();
}
async function dialog_ven() {
if(current_language == "da") {
await dialog_ven_da();
} else {
await dialog_ven_en();
}
}
async function dialog_ven_da() {
let d = new Dialog();
current_dialog = d;
await d.me("hej");
await d.you("tak for sidst!");
await d.you('Har du hørt om den nye EU lov "ChatControl"?');
await d.me("nej, det har jeg ikke");
await d.me("hvad handler det om?");
await d.you('EU kommissionen planlægger at læse alle chatbeskeder i EU');
await d.me('Ja, men vi krypterer jo vores beskeder? Tough luck!');
await d.you('Det tager de højde for. Aflytningen vil ske før krypteringen på din telefon!');
await d.me('Det lyder overhovedet ikke rart. Hvorfor vil de gøre det?');
await d.you('De siger at det er for at beskytte børn på nettet.');
await d.you('Men det giver ikke meget mening');
await d.me('Alle vores beskeder skal scannes på grund af børn på nettet? Det lyder dumt!', true);
await d.you('Her kan du læse mere om det:');
await d.you('https://chatcontrol.dk');
}
async function dialog_ven_en() {
let d = new Dialog();
current_dialog = d;
await d.me("hi");
await d.you("hi, what's up?");
await d.you('Have you heard about the new EU law "ChatControl"?');
await d.me("No, I haven't");
await d.me("What is it about?");
await d.you('The EU commission plans to read all chat messages in the EU');
await d.me('Yeah? But we encrypt all of our chats? Tough luck!');
await d.you('That has been taken into account. The eavesdropping will happen before the encryption step on your phone!');
await d.me('That sounds stupid. Why do they want to do that?');
await d.you('They claim that this is for protecting children on the internet');
await d.you("But that doesn't make any sense.");
await d.me('All of our messages will be scanned because of children on the internet? That sounds really stupid!', true);
await d.you('Here you can read more about it:');
await d.you('https://chatcontrol.dk');
}
async function dialog_mor() {
if(current_language == "da") {
await dialog_mor_da();
} else {
await dialog_mor_en();
}
}
async function dialog_mor_da() {
let d = new Dialog();
current_dialog = d;
await d.you("Jeg har fundet nogle gamle familiebilleder fra vores ferie 10 år siden");
await d.you("Her leger du på stranden");
await d.you("(naked stick figure image here)");
}
async function dialog_mor_en() {
let d = new Dialog();
current_dialog = d;
await d.you("I have found some old family photos from our holiday from 10 years ago");
await d.you("This is you playing on the beach");
await d.you("(naked stick figure image here)");
}
async function dialog_kaereste() {
if(current_language == "da") {
await dialog_kaereste_da();
} else {
await dialog_kaereste_en();
}
}
async function dialog_kaereste_da() {
let d = new Dialog();
current_dialog = d;
await d.me('hej smukkeste');
await d.you('hej, jeg har lige tænkt på dig!');
await d.you('og derfor har jeg taget et sexet billede');
await d.you('#kaereste_foto');
await d.me('tak. Det har jeg savnet!', true);
await d.me('du ser stadig så ung ud.');
await d.me('Jeg tror at vi skal være forsigtige, fordi der er en overvågning af vores beskeder');
await d.you('What the fuck??? Hvem overvågner os?????');
await d.me('Det kan være at udbyderen gør det, fordi de har lov til det');
await d.me("Men i fremtiden vil det faktisk blive forpligtende at scanne beskeder i EU'en");
await d.me('Og hvis der er beskeder som "ligner" børneborno får politiet en kopi af dem');
await d.you('Jeg vil hellere ikke at politiet får mine nøgenbilleder. Det er min krop og jeg vil selv bestemme over det!');
}
async function dialog_kaereste_en() {
let d = new Dialog();
current_dialog = d;
await d.me('Hi beautiful');
await d.you('hi, I just thought about you');
await d.you("and that's why I have taken a sexy picture");
await d.you('#kaereste_foto');
await d.me('Thanks! I missed that!', true);
await d.me('you still look so young.');
await d.me('I think we have to be careful, because our messages are being read');
await d.you('What the fuck??? Who is watching us?????');
await d.me('It can be that the chat provider does this, because they are allowed to search for illegal material');
await d.me('But in the future it will also become mandatory to scan chat messages in the EU');
await d.me('And if a message looks like child pornography then the police will get a copy of it');
await d.you("I don't want to share my nudes with the police. This is my body and I decide who I share it with!");
}
async function dialog_politi() {
if(current_language == "da") {
await dialog_politi_da();
} else {
await dialog_politi_en();
}
}
async function dialog_politi_da() {
let d = new Dialog();
current_dialog = d;
await d.me('Hej, jeg har et spørgsmål');
await d.me('Har du hørt om chatcontrollen og hvad tænker du på det?');
await d.you('Jeg er bekendt med det. Og det er faktisk et ret dårlig idé');
await d.you('Problemet er at der er så mange falsk positive resultater som skal analyseres');
await d.you('Og jeg gider ikke kigge på folkets private beskeder. Det er jo deres fortrolige samtaler');
await d.you('Jeg vil heller ikke at mine kolleger se hvad jeg skriver til min kæreste, kun fordi jeg hypotetisk kunne gøre noget illegalt');
await d.you('Tænk bare hvor absurd idén er: Hvorfor aflytter vi ikke bare alle telefoner? Der vil være nogle forbrydelser vi vil opdage!');
await d.you('Men så har vi den totale overvågning og ikke længere en fri samfund.');
}
async function dialog_politi_en() {
let d = new Dialog();
current_dialog = d;
await d.me('Hi, I have a question');
await d.me('Have you heard about ChatControl and what do you think about it?');
await d.you('I know about it. It is actually a really bad idea');
await d.you('The problem is that there are many false positive hits that need to be analysed manually');
await d.you("And I do not want to read through people's private messages. These are confidential conversations");
await d.you("I don't like that my collegues can potentially see what I write to by partner, just because I could potentially do something illegal while chatting");
await d.you("Just think about how absurd the idea is: Why don't we wiretap all phones? There will be some crimes that we will detect!");
await d.you('But then we have total surveillance and no longer a free society.');
}
async function dialog_support() {
if(current_language == "da") {
await dialog_support_da();
} else {
await dialog_support_en();
}
}
async function dialog_support_da() {
let d = new Dialog();
current_dialog = d;
await d.you('Velkommen til supporten af ChatWorld. Hvad kan jeg hjælpe dig med?');
await d.me('Jeg mistænker at chatprogrammet scanner mine end-to-end krypterede beskeder. Er det rigtigt?');
await d.you('Ja, det er en feature som cheffen ville gerne have.');
await d.you('Der var nogle som har misbrugt chattjenesten til børneporno og det giver meget dårlig publicity og derfor har chefen valgt at scanne end-to-end krypterede beskeder');
await d.you('børneporno er jo en meget dårlig ting. Men jeg synes ikke at det giver mening at aflytte alle private beskeder.');
await d.you('og teknologien kan misbruges til mange ting. Jeg som tekniker kan ikke se hvad søgefunktionen faktisk leder efter.');
await d.you('Det kan være at det vil finde alternative politiske beskeder og markerer det som illegal selv om de ikke er.');
await d.you('Det er en fare for demokratiet hvis fortrolige beskeder bliver scannet for ting som den politiske elite ikke ønsker');
await d.you('Men det er desværre mit job at vedligeholde driften af overvågningen');
await d.me('Det løser ikke mit problem. Men tak for informationen. Jeg vil se hvad jeg kan gør for at undgår overvågningen i fremtiden', true);
await d.you('Beklager at jeg kan ikke tilbyde noget bedre. Men jeg håber at du forstår situationen');
}
async function dialog_support_en() {
let d = new Dialog();
current_dialog = d;
await d.you('Welcome to the ChatWorld support. How can I help you?');
await d.me('I suspect that the chat program is scanning my end-to-end encrypted messages. Am I right?');
await d.you('Yes, that is a feature that our boss wanted to have');
await d.you('Some people have abused the chat service to share child pornography and that gives bad publicity. The boss has therefore chosen to scan all end-to-end encrypted messages');
await d.you("Child pornography is a really bad thing. But I don't think it is sensible to scan all messages.");
await d.you('and the scan technology can be abused for many things. I as a software engineer can not even see what the scanner is searching for');
await d.you("It can be that it will look for alternative political views and marks them as illegal even though they aren't");
await d.you('It is a danger to our democracy when confidential messages are scanned for things that the political elite does not like');
await d.you('But it is unfortunately my job to keep the surveillance working');
await d.me('That does not solve the problem. But thank you for the information. I will look for ways to avoid the surveillance in the future', true);
await d.you('I apologize that I can not offer something better. But I hope you understand the situation');
}
async function dialog_nabopige() {
if(current_language == "da") {
await dialog_nabopige_da();
} else {
await dialog_nabopige_en();
}
}
async function dialog_nabopige_da() {
let d = new Dialog();
current_dialog = d;
await d.you('Gæt hvem har snart fødselsdag!');
await d.me('Det er dig?');
await d.you('Rigtigt! Det var måske for nemt');
await d.me('Hvor gammel bliver du så?');
await d.you('ti');
await d.you('Jeg glæder mig meget til festen. Jeg har inviteret en masse mennesker');
await d.you('Du er også inviteret!');
await d.you('Hej, jeg vil gerne fortælle dig en hjemlighed');
await d.you('Men jeg kan desværre ikke gøre det over chatten');
await d.you('Fordi jeg ved at hvad vi skriver her bliver analyseret');
await d.you('Og det vil ikke være en hjemlighed hvis der er andre læser med');
await d.me('Du kan gerne fortælle mig hjemligheden i morgen, når jeg kommer forbi', true);
await d.me('Jeg er overrasket over at du ved noget om chatovervågningen');
await d.you('Ja, det er meget kedeligt. Jeg har læst noget om det og jeg kan overhovet ikke lide det');
await d.you('Det er bedre hvis man har gode voksne venner som man har tillid til end hvis der er en computer som læser alt hvad man skriver');
await d.me('helt enig');
await d.me('børn har også brug for hjemligheder og fortrolighed!');
}
async function dialog_nabopige_en() {
let d = new Dialog();
current_dialog = d;
await d.you("Guess who's birthday it is soon!");
await d.me("It's yours?");
await d.you('Right! That was maybe too easy');
await d.me('How old will you be?');
await d.you('ten');
await d.you('I am excited for the party. I have invited a lot of people');
await d.you('You are also invited!');
await d.you('Hi, I want to tell you a secret');
await d.you("But I just can't do that in the chat");
await d.you('Because what we write here is being analysed');
await d.you('And it is not going to be a secret when there are others who read the messages');
await d.me('You can tell me the secret tomorrow, when I come to your house', true);
await d.me('I am surprised that you know about the chat surveillance');
await d.you("Yes, it is stupid. I have read about it and I really don't like it");
await d.you('It is better to have adult friends whom I can trust that a computer who reads everything that I write.');
await d.me('Completely agree');
await d.me('Children also need their secrets and confidentiality');
}
]]>
</script>
<!-- [right] contact name view -->
<g id="contact_name_box">
<rect x="300" y="0" width="300" height="50" fill="#F5F5F5"/>
<polyline points="300,20 320,0 320,40" fill="#0084FF" onclick="swipe_viewport()" />
<polyline points="560,20 600,20 580,0" fill="#0084FF" onclick="scroll_up()" />
<polyline points="560,30 600,30 580,50" fill="#0084FF" onclick="scroll_down()" />
<text x="325" y="30" id="contact_indicator">loading...</text>
<use href="#flag_denmark" x="500" y="35" onclick="switch_language('da')" />
<g transform="scale(0.5,0.5)">
<use href="#flag_uk" x="1050" y="70" onclick="switch_language('en')" />
</g>
</g>
<!-- [right] messages view -->
<rect id="message_box" x="300" y="50" width="300" height="450" fill="white" />
<g id="messages"></g>
<!-- [right] message status -->
<rect id="message_status_box" x="300" y="520" fill="#FF7B00" width="300" height="30" />
<text id="message_status" x="310" y="540" fill="white">status</text>
<!-- [right] text input -->
<rect id="message_input_box" x="300" y="550" stroke="black" fill="white" width="250" height="50" />
<rect id="message_submit_box" x="550" y="550" stroke="black" fill="#CCCCCC" width="50" height="50" />
<text id="message_input_data" x="310" y="575" fill="black"></text>
<text id="message_submit_button" x="555" y="580" fill="black">SEND</text>
<!-- [left] contact list -->
<rect x="0" y="0" width="300" height="50" fill="#E4E6EB" />
<text x="60" y="30">Dine kontakter</text>
<rect x="0" y="50" width="300" height="550" style="stroke: green; stroke-width: 0px" fill="white" />
<text x="15" y="75" onclick="start_chat('Ven')">Ven</text>
<text x="15" y="100" onclick="start_chat('Mor')">Mor</text>
<text x="15" y="125" onclick="start_chat('Kæreste')">Kæreste&#10084;</text>
<text x="15" y="150" onclick="start_chat('Politiven')">Politiven</text>
<text x="15" y="175" onclick="start_chat('ChatSupport')">Chat Support</text>
<text x="15" y="200" onclick="start_chat('Nabopige')">nabopige</text>
</svg>

After

Width:  |  Height:  |  Size: 27 KiB

14
index.html Normal file
View file

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<title>redirecting</title>
<meta http-equiv="refresh" content="0;url=da" />
</head>
<body>
<p>Redirecting...</p>
<p>
<a href="da">dansk</a>
<a href="en">english</a>
</p>
</body>
</html>

34
style.css Normal file
View file

@ -0,0 +1,34 @@
.besked {
color: #FFFFFF;
background-color: #0084FF;
border-radius: 25px;
padding-top: 10px;
padding-bottom: 10px;
padding-left: 20px;
padding-right: 20px;
}
p {
margin-left: 10px;
border: 1px dashed black;
padding: 5px;
max-width: 800px;
}
#app-area {
display: grid;
grid-template-columns: 350px 300px;
gap: 10px;
grid-auto-rows: minmax(350px, auto);
}
#movie {
margin-left: 10px;
grid-column: 1;
grid-row: 1;
}
#movie-sidetext {
grid-column: 2;
grid-row: 1;
}