Kokkoja as of 2026-10-10: the teacher's requests, the Session window, notices, the QR code, the license
This commit is contained in:
1 parent
95c80d04c9
commit
1d087af633
32 files changed
+4917
-890
No files matched your search
+144
-83
@@ -14,22 +14,28 @@ chat message, a text message. It is a link of this shape:
|
||||
|
||||
The part after `join=` is the invitation itself, which the host's Kokkoja
|
||||
may also give you on its own, without the link around it. Both forms
|
||||
work wherever an invitation is asked for. The invitation carries the key
|
||||
work wherever an invitation is asked for. A host in the same room may
|
||||
instead show you the link as a QR code on their screen: point your
|
||||
phone's or tablet's camera at it and open the link it offers. The invitation carries the key
|
||||
that protects the session, so pass it on only to people who belong in the
|
||||
session, and treat it as you would a meeting link. An invitation is good
|
||||
for one session: the host's next session has a new one.
|
||||
|
||||
## Joining
|
||||
|
||||
Open the link in a web browser. Firefox, Brave and Chrome are known to
|
||||
work; other browsers built on the same engines very probably do. You see
|
||||
Kokkoja's start screen with the invitation already filled in. Enter the
|
||||
name the others should see and press **Join**. That is all: nothing is
|
||||
installed, and there is no account to make.
|
||||
Open the link in a web browser. Firefox, Brave and Chrome on a
|
||||
computer, and Safari on an iPad or an iPhone, are known to work; other
|
||||
browsers built on the same engines very probably do. You see
|
||||
Kokkoja's start screen, headed "Join a session", with the invitation
|
||||
already filled in. Enter the name the others should see and press
|
||||
**Join**. That is all: nothing is installed, and there is no account to
|
||||
make. (Opened without an invitation, the same screen also offers to
|
||||
start a session of your own; an invitation is a request to join one
|
||||
session, so with one it offers joining alone.)
|
||||
|
||||
Your name is remembered by the browser for next time. So is a second
|
||||
field, **Notebook for the pages of this session**, which you can leave as
|
||||
it is for now; what it does is explained under "Your notebook" below.
|
||||
choice, **Notebook for the pages of this session**, which you can leave
|
||||
as it is for now; what it does is explained under "Your notebook" below.
|
||||
|
||||
If you have the Kokkoja program installed on your computer (see
|
||||
[A host's Kokkoja](host.md) for what that is and why you might want it),
|
||||
@@ -42,15 +48,17 @@ place in it waits for the host to return.
|
||||
|
||||
## The screen
|
||||
|
||||
Across the top is the toolbar. On the left are the tools and their
|
||||
settings; on the right, the zoom and, for the host, the buttons that
|
||||
start pages. Below it, the page fills most of the window, with a panel on
|
||||
the right. Every button explains itself: rest the pointer on it for a
|
||||
second and its explanation appears beneath it.
|
||||
Across the top is the toolbar, one row holding everything: the tools
|
||||
and their settings, the view, the host's page buttons, your notebook,
|
||||
and **Session**, which opens a window with the participants and the
|
||||
invitation. Below it the page has the whole width of the window. Every button
|
||||
explains itself: rest the pointer on it for two seconds and its
|
||||
explanation appears beneath it.
|
||||
|
||||
### The page
|
||||
|
||||
The page is an A4 sheet, shown so that it fits the window. Write
|
||||
The page is an A4 sheet lying on its side, shown so that it fits the
|
||||
window. Write
|
||||
anywhere on it. When your writing comes near an edge, the sheet grows in
|
||||
that direction, in small steps, so there is always room, and the view
|
||||
keeps its scale and extends beyond the window; scroll to reach the rest.
|
||||
@@ -65,11 +73,12 @@ is scrolled to concern nobody else.
|
||||
|
||||
**Pen** is chosen when you arrive. Draw with a pen on a tablet, a mouse,
|
||||
or a finger on a touch screen. With a pen, pressing harder makes the
|
||||
line wider. The colours are to the right of the tools: black, blue, red
|
||||
and green, and **+** opens a palette of more. A colour chosen from the
|
||||
palette joins the row of colours and stays there in this browser. The
|
||||
three lines to the right of the colours are the line widths: 0.4, 0.7
|
||||
and 1.2 mm at ordinary pressure.
|
||||
line wider. The colours are to the right of the tools: black, red,
|
||||
green, blue and white, and **+** opens a palette of more, in which the
|
||||
colours already in the row leave their places empty. A colour chosen
|
||||
from the palette joins the row and stays there in this browser. White
|
||||
is for painting over. The four lines to the right of the colours are
|
||||
the line widths: 0.4, 0.7, 1.2 and 2.4 mm at ordinary pressure.
|
||||
|
||||
If a pen is in use, a hand resting on a touch screen is ignored.
|
||||
|
||||
@@ -78,17 +87,25 @@ If a pen is in use, a hand resting on a touch screen is ignored.
|
||||
**Text** types on the page. Tap where the text should begin and type; a
|
||||
text field appears there and the text is laid out on the page as you
|
||||
type. Enter begins a new line. Press Escape, or tap somewhere else, to
|
||||
finish; a block with nothing in it disappears.
|
||||
finish; a block with nothing in it disappears. You need not finish to
|
||||
move a block: rest the pen on it while typing, and it follows the pen,
|
||||
field and all; lift, and go on typing.
|
||||
|
||||
A block made by a tap does not wrap: its lines are as long as you type
|
||||
them, and the page grows to hold them. To make the text wrap at a chosen
|
||||
width, drag along where its top edge should run instead of tapping: the
|
||||
block begins at the left end of the drag and wraps at the right end.
|
||||
them, and the page grows to hold them; a red corner mark of 5 mm at its
|
||||
top left shows where it begins. To make a *text rectangle*
|
||||
instead, drag it open where you want it: a red box, white inside, in
|
||||
which the text wraps at the box's width, and which grows downward by
|
||||
lines when you type more than it holds. The box is part of the page,
|
||||
seen by everyone, and where it lies over an image it covers the image
|
||||
and nothing else; a teacher uses one to say "write your answer here".
|
||||
|
||||
Tap your own text to change it. While a block of yours is being edited
|
||||
it is drawn grey, and three handles appear: the one at its top-left
|
||||
corner and the line along its top edge move it, the one at the right end
|
||||
of that line changes its width. You cannot change anyone else's text.
|
||||
Tap your own text to change it, anywhere in a box, and the cursor is at
|
||||
the end of the text. To move a block of yours, rest the pen
|
||||
on it, without moving, for a little over half a second: a green outline
|
||||
appears, and it follows the pen. To resize a text rectangle, rest the
|
||||
pen near one of its corners and drag the corner; the text wraps anew at
|
||||
the new width. You cannot change anyone else's text.
|
||||
|
||||
With the Text tool, the row of colours stays and the line widths give way
|
||||
to the font, one of **Sans**, **Serif** and **Mono**, and the size in
|
||||
@@ -102,48 +119,79 @@ whole stroke goes; across a text block and the block goes. It removes
|
||||
nothing of anyone else's, and nobody else's eraser can touch yours. An
|
||||
erased stroke is gone from the page for everyone.
|
||||
|
||||
### Zoom
|
||||
### The view
|
||||
|
||||
**Fit** shows the whole page in the window, and keeps doing so as the
|
||||
page grows by writing, except while you are in the middle of a stroke of
|
||||
your own. **+** and **−** zoom in and out by a tenth. Holding Ctrl and
|
||||
turning the scroll wheel zooms about the pointer. When the page is
|
||||
larger than the window, scroll it as you would any page. When the host
|
||||
adds an image, the view keeps its scale rather than shrinking to fit; a
|
||||
new image at the bottom of a long page is reached by scrolling.
|
||||
A page is shown whole when you first see it. Afterwards the view keeps
|
||||
its scale: when the page grows, or the host adds an image, the page
|
||||
extends beyond the window and you scroll to the rest. Three buttons and
|
||||
two gestures change the view, and none of them changes the page:
|
||||
|
||||
* **Fit** shows the whole page in the window.
|
||||
* **A4** shows the page at the scale a new page has, one A4 sheet
|
||||
filling the window, so that a page shrunk to a small exercise is seen
|
||||
at its size on the sheet rather than enlarged to fill the window.
|
||||
* When the host presses **Fit** or **A4**, every participant's view
|
||||
follows, each in their own window. Your own Fit and A4 change only
|
||||
your screen.
|
||||
* **Widen**, which only the host and co-hosts have, makes the page
|
||||
itself wider, for everyone, until it fills the
|
||||
window at the present zoom. The sheet grows equally on both sides,
|
||||
so nothing on the page moves and nothing is rescaled; there is simply
|
||||
more room at either side.
|
||||
* **Shrink**, also for the host and co-hosts, makes the page, for everyone, just large enough for what is on it,
|
||||
with the usual margin around. Nothing on it moves either.
|
||||
* **Extend** is a box, ticked to begin with. Ticked, the sheet grows
|
||||
when your writing comes near an edge, so there is always room.
|
||||
Unticked, your writing stops short of the edge; a stroke that leaves
|
||||
the page resumes when the pen comes back. Images always get the room
|
||||
they need.
|
||||
* Hold **Ctrl** (Command on a Mac) and turn the scroll wheel to zoom in
|
||||
and out about the pointer.
|
||||
* Hold **Ctrl** (Command on a Mac) and draw a stroke with the pen: up
|
||||
zooms in, down zooms out, by twice for every 100 pixels of movement,
|
||||
about the point where the pen touched down. Nothing is drawn while
|
||||
the key is held.
|
||||
|
||||
If you reload the browser tab, it comes back to the page as you last saw
|
||||
it: same zoom, same place.
|
||||
|
||||
### The panel
|
||||
### Session
|
||||
|
||||
**Participants** lists everyone in the session, with *you* and *host*
|
||||
marked, and *away* beside anyone who has left or lost their connection;
|
||||
an absent participant's writing stays on the page. The box in front of
|
||||
each name shows or hides that participant's writing on your screen alone.
|
||||
Hiding your teacher's corrections to try an exercise again, or hiding
|
||||
your own answers to see the exercise as it was, changes nothing for
|
||||
anyone else.
|
||||
**Session** in the toolbar opens a window with the people and the
|
||||
invitation. **Participants** lists everyone in the session, with *you*
|
||||
and *host* marked, and *away* beside anyone who has left or lost their
|
||||
connection; an absent participant's writing stays on the page. The box
|
||||
in front of each name shows or hides that participant's writing on your
|
||||
screen alone. Hiding your teacher's corrections to try an exercise
|
||||
again, or hiding your own answers to see the exercise as it was,
|
||||
changes nothing for anyone else.
|
||||
|
||||
**Invitation** shows the invitation of this session, with a button to
|
||||
copy it, in case someone else should be invited.
|
||||
copy it and, below, as a QR code for a camera, in case someone else
|
||||
should be invited. **Log** is a record of what happened in this
|
||||
session, pages and connection and every press and release of the pen,
|
||||
with a button to copy it: if something goes wrong, copy it and send it
|
||||
to whoever looks after Kokkoja. Above it the window says which page
|
||||
you are on, counted from the start of the session, how you stand with
|
||||
the relay, and when the page was last saved; below it, where your
|
||||
notebooks are kept.
|
||||
|
||||
**Current notebook**, **Keep page** and **Export** concern your notebook,
|
||||
below. Under them, a line reports what was last saved, and whether
|
||||
anything went wrong.
|
||||
### Notices
|
||||
|
||||
The last line of the panel reports what your pen or mouse is delivering:
|
||||
the kind of device, the pressure, and how many positions per second it
|
||||
sends. It is there for curiosity and for finding faults.
|
||||
While all is well Kokkoja says nothing. When there is something to
|
||||
know, a line appears between the toolbar and the page: in red while
|
||||
a problem lasts, in grey for a few seconds after something was done.
|
||||
*Not connected. Reconnecting…* means the relay cannot be reached;
|
||||
Kokkoja reconnects by itself, and what you wrote meanwhile is sent when
|
||||
it returns. *The page could not be saved* means the notebook is out of
|
||||
reach; the page is still in memory and the saving is tried again.
|
||||
*Waiting for the host's page* means the host has not started a page
|
||||
yet, or your connection is down. The grey notices say that a page was
|
||||
kept or exported, and where.
|
||||
|
||||
### Status
|
||||
|
||||
At the right end of the toolbar, **Page 3** is the number of the page you
|
||||
are on, counted from the start of the session, and beside it *Connected*,
|
||||
*Connecting…* or *Disconnected* says how you stand with the relay. If
|
||||
the connection drops, Kokkoja reconnects by itself; what you wrote while
|
||||
disconnected is sent when it returns. Until the host has started a
|
||||
page, the toolbar says *Waiting for the host's page*.
|
||||
For finding faults, the browser's console (F12) keeps a short log of the
|
||||
session's events: pages, images, the connection, and what your pen or
|
||||
mouse delivers.
|
||||
|
||||
## Your notebook
|
||||
|
||||
@@ -162,24 +210,28 @@ last changed and the number counting the pages kept that day.
|
||||
|
||||
Two buttons bring pages out of the browser:
|
||||
|
||||
* **Keep page** keeps a dated copy of the page as it is now, and
|
||||
* **Keep** keeps a dated copy of the page as it is now, and
|
||||
downloads it, so you find it among your browser's downloads. Pressing
|
||||
it again before anything has changed makes no second copy.
|
||||
it again before anything has changed makes no second copy and no
|
||||
second download. Any mark counts as a change, even a dot from a
|
||||
stray touch of the pen.
|
||||
* **Export** downloads a picture of the page as you see it, as a PNG
|
||||
file; writing you have hidden is left out. Its name is the date and
|
||||
the page number.
|
||||
|
||||
A page file is an SVG file. Any web browser displays it, and vector
|
||||
drawing programs such as Inkscape open it. Kokkoja itself can load one
|
||||
again, writing and all, when someone with the right to start pages
|
||||
chooses it (see "When the host gives you more" below, and the host's
|
||||
again, writing and all, when the host or a co-host chooses it (see "When the host gives you more" below, and the host's
|
||||
part).
|
||||
|
||||
The notebook field on the start screen names the notebook within the
|
||||
The notebook list on the start screen names the notebook within the
|
||||
browser's storage. Giving each course or each colleague a notebook of
|
||||
their own keeps their pages apart; the name proposed is simply
|
||||
*Notebook*. **Current notebook** in the panel shows the notebook in use
|
||||
and lets you change it during the session.
|
||||
their own keeps their pages apart; until you make one, everything goes
|
||||
into the notebook *General*. The last entry of the list, **New
|
||||
notebook…**, asks for a name and makes a notebook of that name; it
|
||||
exists from the moment a page is written into it. **Current notebook**
|
||||
in the toolbar is the same list, and lets you change notebook, or make
|
||||
one, during the session.
|
||||
|
||||
### On your computer
|
||||
|
||||
@@ -193,7 +245,7 @@ to open the invitation in the installed program.
|
||||
|
||||
With the program, a notebook is a directory in `Kokkoja` in your
|
||||
Documents directory. The page you are on is `Current.svg` there, and
|
||||
kept pages lie beside it under their dated names. **Keep page** makes
|
||||
kept pages lie beside it under their dated names. **Keep** makes
|
||||
the dated copy; **Export** opens Kokkoja's own file chooser, in which you
|
||||
pick a directory and a name for the PNG file.
|
||||
|
||||
@@ -210,35 +262,44 @@ still on the page, from the others' copies and from your notebook, and
|
||||
it is still yours to erase or change. A tab that was in a session and is
|
||||
reloaded goes straight back in.
|
||||
|
||||
## When the host gives you more
|
||||
## When the host makes you a co-host
|
||||
|
||||
Normally only the host puts images on the page, starts new pages, or
|
||||
loads pages from a notebook. The host can give you the same right, for
|
||||
instance in a discussion among colleagues where everyone brings
|
||||
material. When that happens, three more buttons appear at the right of
|
||||
your toolbar:
|
||||
loads pages from a notebook. The host can make you a *co-host*, which
|
||||
gives you the same powers, for instance in a discussion among
|
||||
colleagues where everyone brings material. The Session window then
|
||||
says *co-host* beside your name, and three more buttons appear at the
|
||||
right of your toolbar:
|
||||
|
||||
* **New** starts a new blank page for everyone. The page being left is
|
||||
kept in each person's notebook.
|
||||
* **Image** puts an image file on the page for everyone, below any
|
||||
images already there. Your browser's file chooser asks for the file
|
||||
(with the Kokkoja program, Kokkoja's own chooser does, beginning where
|
||||
the notebooks are, with a choice whether an image wider than the page
|
||||
is shrunk to fit it). A PNG or JPEG file keeps its exact pixels unless
|
||||
the notebooks are). A PNG or JPEG file keeps its exact pixels unless
|
||||
it is very large; other formats and very large images are converted
|
||||
and reduced before they are shared. An image is placed at its natural
|
||||
size, centred, 8 mm from the top or from the image above; one wider
|
||||
than the sheet is scaled down to fit between the margins. To put an
|
||||
image on a page of its own, press **New** first.
|
||||
size, centred, 5 mm below the image above or at the top of the page;
|
||||
one wider than the page widens it. To put an image on a page of its
|
||||
own, press **New** first.
|
||||
* **Notebook** starts a new page for everyone from a page kept in one of
|
||||
your notebooks, with everything that was written on it. A chooser
|
||||
shows your notebooks and small pictures of their kept pages. The kept
|
||||
page itself is not changed: the session works on a copy.
|
||||
* **Hide**, among the tools, hides part of the page for everyone: drag
|
||||
open a rectangle and whatever lies under it, writing included, is
|
||||
covered in white, marked by blue corners so that nobody writes there
|
||||
unknowingly. Rest the pen on it to move it, near a corner to resize
|
||||
it; a tap of the eraser removes it and uncovers what was there. A Hide
|
||||
stays even for someone who hides your writing on their own screen.
|
||||
|
||||
An image cannot be moved or removed once anyone has written on it or
|
||||
added anything after it, since the marks on it would make no sense
|
||||
without it. The one exception is a mistake caught at once: the person
|
||||
who added an image can take it back with a tap of the eraser on it, as
|
||||
long as nothing else has happened on the page since.
|
||||
As a co-host you can also move and scale images, as the host can: rest the pen on an image for a little over half a second
|
||||
and it follows the pen; rest it near a corner and the corner follows,
|
||||
the shape kept. Writing stays where it is, so images are arranged
|
||||
first and written on afterwards. A new image always arrives below the
|
||||
others, centred, at its own size, to be arranged by hand. A tap of the
|
||||
eraser on an image removes it; writing on it stays. An image you added
|
||||
yourself you may always remove, even after you have stopped being a
|
||||
co-host.
|
||||
|
||||
The right stays with you until the host withdraws it or the session ends.
|
||||
You stay a co-host until the host decides otherwise or the session ends.
|
||||
+142
-47
@@ -22,21 +22,44 @@ You need:
|
||||
`python3 --version`; if Python is not installed, macOS offers to
|
||||
install the command line developer tools, which include it. Any Python
|
||||
from 3.9 on will do.
|
||||
* **A web browser.** Firefox, Brave or Chrome; other browsers built on
|
||||
the same engines very probably work.
|
||||
* **A web browser.** Firefox, Brave or Chrome, or Safari on a Mac;
|
||||
other browsers built on the same engines very probably work.
|
||||
* **A pen tablet**, if you want to write by hand. A mouse works for
|
||||
pointing and for rough marks.
|
||||
|
||||
Get Kokkoja from its repository, either by downloading it as a zip file
|
||||
and unpacking it, or with git:
|
||||
Get Kokkoja from its repository: download
|
||||
|
||||
https://git.andykopra.com/ack/kokkoja-rel/archive/main.zip
|
||||
|
||||
and unpack it, or, if you have git,
|
||||
|
||||
git clone https://git.andykopra.com/ack/kokkoja-rel.git kokkoja
|
||||
|
||||
Nothing else is installed and nothing is changed on your system. To
|
||||
update later, download again or run `git pull` in that directory. To
|
||||
update later, download again or run `git pull` in that directory.
|
||||
Kokkoja is free software under the GNU General Public License; the
|
||||
`LICENSE.md` file in the directory is the license. To
|
||||
remove Kokkoja, delete the directory; your notebooks are elsewhere and
|
||||
stay.
|
||||
|
||||
### On a Mac
|
||||
|
||||
The same steps, with four things to know:
|
||||
|
||||
* Terminal is in Applications → Utilities. The first `python3` or
|
||||
`git` command may make macOS offer to install the command line
|
||||
developer tools; accept, and run the command again when it has
|
||||
finished.
|
||||
* The first time the program writes a notebook, macOS asks whether
|
||||
Terminal may reach your Documents folder. Allow it, once; the
|
||||
notebooks are there. The answer can be changed later under System
|
||||
Settings → Privacy & Security → Files and Folders.
|
||||
* The program opens Kokkoja in your default browser, Safari included.
|
||||
To use another, start the program with `--no-browser` and open the
|
||||
address it prints in the browser you prefer.
|
||||
* Wherever this documentation says Ctrl for zooming, use Command on a
|
||||
Mac. Both work, so a hand used to Ctrl is not punished.
|
||||
|
||||
## Starting Kokkoja
|
||||
|
||||
Open a terminal in the Kokkoja directory and run
|
||||
@@ -57,8 +80,13 @@ The relay address names the *Kokkoja server* you use. A server does two
|
||||
things: it passes the participants' messages, encrypted so that it
|
||||
cannot read them, and it serves the web site that your guests join from.
|
||||
The address above is Andy's server; whoever runs a server for you gives
|
||||
you its address. If you give the program no relay, it expects one on
|
||||
your own computer, which is useful only for trying Kokkoja alone.
|
||||
you its address. The program remembers it, so from the second time on
|
||||
|
||||
python3 kokkoja.py
|
||||
|
||||
is enough, and the program says which relay it is using. Give the
|
||||
option again only to change servers. Started for the first time with no
|
||||
relay, it stops and asks for one.
|
||||
|
||||
Other options, all optional:
|
||||
|
||||
@@ -73,28 +101,34 @@ Other options, all optional:
|
||||
## Starting a session
|
||||
|
||||
On the start screen, enter your name and the notebook for this session,
|
||||
and press **Start a session**. You are on page 1, a blank sheet, and the
|
||||
panel on the right shows the invitation.
|
||||
and press **Start a session**. You are on page 1, a blank sheet, and
|
||||
**Session** in the toolbar shows the invitation.
|
||||
|
||||
### The notebook
|
||||
|
||||
The notebook you name is a directory under `Kokkoja` in your Documents
|
||||
directory, made when it is first needed, and the start screen offers the
|
||||
names of the notebooks you already have. For teaching, a notebook per
|
||||
student works well: everything a student is given, with everything they
|
||||
and you wrote on it, gathers in that student's notebook, and the next
|
||||
lesson with that student starts by naming it again. Your library of
|
||||
exercises can live in notebooks of its own, such as *Exercises A1*, filled
|
||||
by keeping pages in a session of your own with nobody else present.
|
||||
A notebook is a directory under `Kokkoja` in your Documents directory.
|
||||
The start screen lists the notebooks you have; until you make one, there
|
||||
is *General*, the notebook for whatever has no notebook of its own. The
|
||||
last entry of the list, **New notebook…**, asks for a name and makes a
|
||||
notebook of that name, which exists from the moment a page is written
|
||||
into it. For teaching, a notebook per student works well: everything a
|
||||
student is given, with everything they and you wrote on it, gathers in
|
||||
that student's notebook, and the next lesson with that student starts
|
||||
by choosing it again. Your library of exercises can live in notebooks
|
||||
of its own, such as *Exercises A1*, filled by keeping pages in a session
|
||||
of your own with nobody else present.
|
||||
|
||||
The notebook can be changed during a session, in **Current notebook** in
|
||||
the panel. The page you are on then continues in the new notebook.
|
||||
The notebook can be changed during a session, in the notebook list in
|
||||
the toolbar. The page you are on then continues in the notebook chosen.
|
||||
|
||||
### The invitation
|
||||
|
||||
**Invitation** in the panel shows a link. **Copy** copies it; send it to
|
||||
**Session** in the toolbar opens a window; **Invitation** there shows a
|
||||
link. **Copy** copies it; send it to
|
||||
your guests by email, in a chat message, or however you reach them. A
|
||||
guest opens it, enters a name and is in. A guest with the Kokkoja
|
||||
guest opens it, enters a name and is in. Below the link the same
|
||||
invitation stands as a QR code: a guest with a phone or a tablet points
|
||||
its camera at your screen, and the link opens there. A guest with the Kokkoja
|
||||
program installed may paste it into their own program instead. The link
|
||||
carries the secret that protects the session, so send it only to those
|
||||
who should be there; anyone with the link can join and read the page.
|
||||
@@ -115,24 +149,72 @@ notebook, by itself, under a dated name; nobody has to remember to save.
|
||||
file chooser opens, beginning where your notebooks are and remembering
|
||||
where you last chose from; a directory path can also be typed into it.
|
||||
It shows small pictures of the image files it finds. Choose one and it
|
||||
is placed on the page: the first at the top of the sheet, each further
|
||||
one 8 mm below the lowest image there, centred, at its natural size. An
|
||||
image wider than the sheet is scaled down to fit between the margins, so
|
||||
a full-page A4 scan appears at about 92%; the chooser has a setting to
|
||||
turn that off, in which case the sheet widens to the image instead. PNG
|
||||
and JPEG files are shared as they are unless very large; other formats,
|
||||
and images over 2400 pixels on a side or 1.5 MB, are converted to JPEG
|
||||
and reduced first. A page holds up to 12 images.
|
||||
is placed on the page in one way always: 5 mm below the lowest image
|
||||
there, or at the top of the page if there is none, centred across the
|
||||
page's width, at its natural size, in front of the images already
|
||||
there. Natural size is the size the file records: a scan arrives at
|
||||
the size of the paper it came from. A photo from a phone or camera
|
||||
records no useful size and arrives at a tenth of a millimetre per
|
||||
pixel. An image wider than the page widens the page on both sides to
|
||||
hold it. From there you move and scale it by hand, as described next;
|
||||
there is no other setting to choose. PNG and JPEG files are shared as
|
||||
they are unless very large; other formats, and images over 2400 pixels
|
||||
on a side or 1.5 MB, are converted to JPEG and reduced first, which
|
||||
does not change the size they arrive at. A page holds up to 12 images.
|
||||
|
||||
To move an image, rest the pen on it, without moving, for a little over
|
||||
half a second: a green outline appears, and the image follows the pen
|
||||
until you lift it. It comes to the front of the other images, which a
|
||||
hold without moving also does. To scale an image, rest the pen near one
|
||||
of its corners: a green square marks the corner, and dragging it scales
|
||||
the image along its diagonal, the opposite corner staying put and the
|
||||
shape kept. This works with every tool: a dot the pen may have drawn
|
||||
while resting is removed, and the eraser erases nothing while it rests.
|
||||
Writing is not attached to images: an image moved from under writing
|
||||
leaves the writing where it was, so compose the images first and write
|
||||
afterwards. Only you and co-hosts can move images.
|
||||
|
||||
For a page that begins with an image, press **New** and then **Image**.
|
||||
For a series of exercises, keep pressing **Image** on the same page: the
|
||||
sheet grows downward and everyone scrolls through them. A new image does
|
||||
not change anyone's zoom; it appears below, to be scrolled to.
|
||||
|
||||
If you chose the wrong file, a tap of the eraser on the image takes it
|
||||
back, as long as nothing else has happened on the page since: no stroke,
|
||||
no text, no erasure, no further image, by anyone. After that an image
|
||||
stays, because the marks made on it would make no sense without it.
|
||||
A tap of the eraser on an image removes it, whoever added it and
|
||||
whenever. Writing on it stays where it was, so remove an image before
|
||||
anyone writes on it unless the writing is meant to stay. The page keeps
|
||||
the size the image gave it; **Shrink** trims it. A guest who added an
|
||||
image may remove it, even after they have stopped being a co-host.
|
||||
|
||||
**Fit** and **A4**, pressed by you, act on every participant's screen,
|
||||
each in their own window: the way to bring everyone back to the whole
|
||||
page. A guest's Fit and A4 change only that guest's screen.
|
||||
|
||||
**Hide**, the tool beside the Eraser, covers part of the page for
|
||||
everyone: drag open a rectangle, and whatever lies under it, writing of
|
||||
anyone included, is covered in white, marked by blue corners that tell
|
||||
the students something is there. Use it to cover a solution until the
|
||||
student has tried, or a part of the exercise for later. Rest the pen on
|
||||
it to move it, near a corner to resize it; a tap of the eraser removes
|
||||
it and shows what was covered. Nothing under a Hide is lost, and a
|
||||
student cannot uncover it by hiding your writing on their screen: a Hide
|
||||
belongs to the page, not to your writing. A Hide is white in an
|
||||
exported picture and in the page file as other programs see it.
|
||||
|
||||
With the Text tool, a rectangle dragged open is a *text rectangle*: a
|
||||
red box with a white ground, which covers the image beneath it and no
|
||||
writing, in which text wraps and which grows downward as it fills. It
|
||||
is the "write your answer here" box of a worksheet: draw it on the scan
|
||||
where the answer belongs, and the student types into their own box or
|
||||
beside yours. Only its owner can type in a box, as with any text.
|
||||
|
||||
**Widen**, among the view buttons, makes the page wider for everyone,
|
||||
until it fills your window at your present zoom: the quickest way to
|
||||
more room for writing beside an exercise. The sheet grows equally on
|
||||
both sides, so nothing on the page moves. The page keeps the new width
|
||||
in everyone's notebook. **Shrink** is its opposite: the page becomes
|
||||
just large enough for everything on it, images and writing, with the
|
||||
margin of 5 mm around, which trims a page down to its exercise before you keep
|
||||
or export it. A blank page cannot shrink.
|
||||
|
||||
**Notebook** starts a new page for everyone from a page kept in one of
|
||||
your notebooks, with everything that was written on it. A chooser shows
|
||||
@@ -147,14 +229,17 @@ was kept when you left it, and **Notebook** brings it back as a new page.
|
||||
A lesson might go: **New**, **Image** for the exercise, work, **New**
|
||||
for a point of grammar, work, **Notebook** to return to the exercise.
|
||||
|
||||
## Guests' rights
|
||||
## Co-hosts
|
||||
|
||||
In the **Participants** list, each guest's name has a button **pages** in
|
||||
front of it. Pressing it lets that guest start new pages, put images on
|
||||
the page and load pages from their notebook, exactly as you can; the
|
||||
three buttons appear on their toolbar. Pressing it again withdraws the
|
||||
right, which otherwise lasts until the session ends. Guests can never erase or
|
||||
change anyone's writing but their own; that needs no setting.
|
||||
In the **Participants** list of the Session window, each guest's name
|
||||
has a box **Co-host** beside it. Ticking it makes that guest a
|
||||
co-host: they may then start new pages, put images on the page and
|
||||
arrange them, load pages from their notebook, widen, shrink and hide,
|
||||
exactly as you can, and the buttons for it appear on their toolbar.
|
||||
Unticking it takes it back; otherwise it lasts until the session
|
||||
ends. What stays yours alone: making co-hosts, and bringing everyone's
|
||||
view to the page with Fit or A4. Guests, co-hosts or not, can never
|
||||
erase or change anyone's writing but their own; that needs no setting.
|
||||
|
||||
## Hiding writing
|
||||
|
||||
@@ -169,9 +254,10 @@ picture of the exercise with the corrections alone.
|
||||
|
||||
The page you are on is written continuously to `Current.svg` in the
|
||||
current notebook, and copied to a dated file whenever the session moves
|
||||
on. **Keep page** makes such a copy now, named for the day and a serial
|
||||
on. **Keep** makes such a copy now, named for the day and a serial
|
||||
number, such as `2026_10_06_02.svg`; pressing it again before anything
|
||||
has changed makes no second copy. Use it to mark a state worth keeping
|
||||
has changed makes no second copy. Any mark counts as a change, even a
|
||||
dot from a stray touch of the pen. Use it to mark a state worth keeping
|
||||
on its own, or to add a finished page to a notebook of exercises.
|
||||
|
||||
**Export** saves a picture of the page as you see it, as a PNG file at
|
||||
@@ -190,7 +276,7 @@ Close the browser tab, or stop the program with Ctrl-C in its terminal.
|
||||
There is nothing to save: the page is already in your notebook, and in
|
||||
each guest's. Guests who are still connected can go on writing on the
|
||||
page among themselves, but no new page can be started without you or a
|
||||
guest you have given the right, and a guest who arrives after everyone
|
||||
co-host, and a guest who arrives after everyone
|
||||
has left finds an empty session. The next lesson is a new session with a
|
||||
new invitation; load the pages you need from the student's notebook.
|
||||
|
||||
@@ -199,13 +285,22 @@ new invitation; load the pages you need from the student's notebook.
|
||||
* **The browser says the notebooks are locked.** Open Kokkoja from the
|
||||
full address the program printed when it started, the one with the
|
||||
token.
|
||||
* **"Disconnected" in the toolbar.** Kokkoja reconnects by itself as
|
||||
* **"Not connected" above the page.** Kokkoja reconnects by itself as
|
||||
soon as the relay can be reached, and sends what was written meanwhile.
|
||||
If it does not come back, check your connection; the page is safe in
|
||||
your notebook either way.
|
||||
* **A guest sees "Waiting for the host's page".** You have not started
|
||||
a page yet, or your connection is down. The first page is started when
|
||||
you start the session, so this usually means the latter.
|
||||
* **Pressure does not work.** The last line of the panel reports what
|
||||
the browser receives from your pen. If it says *mouse*, the browser is
|
||||
not seeing the pen as a pen; try the other browser.
|
||||
* **Pressure does not work.** The browser's console (F12) logs what
|
||||
the browser receives from your pen at your first stroke. If it says
|
||||
*mouse*, the browser is not seeing the pen as a pen; try the other
|
||||
browser.
|
||||
* **"Address already in use" when starting the program.** A copy of
|
||||
the program is already running, usually in another terminal window.
|
||||
Only one can run at a time; use it, or stop it there with Ctrl-C and
|
||||
start again.
|
||||
* **Guests cannot connect.** Look at the line `Relay: ...` the program
|
||||
printed when it started: it names the relay the session goes through.
|
||||
If it is not your server's address, stop the program and start it
|
||||
again with `--relay` and the right address.
|
||||
+68
-20
@@ -37,13 +37,16 @@ page, an image once. There is no central copy.
|
||||
|
||||
Two computers behind home routers generally cannot connect to each other
|
||||
directly, so something in between has to pass the messages. The relay is
|
||||
the smallest such thing: a WebSocket server with *rooms*. A client
|
||||
connects to `wss://<server>/relay/room/<room id>`; the relay gives the
|
||||
connection a number, tells the room that a peer has arrived, and from
|
||||
then on sends every message it receives from one member to all the
|
||||
others, stamped with the sender's number. When the last member leaves,
|
||||
the room is gone. It holds at most 32 members per room and 500 rooms,
|
||||
and refuses messages over 1 MB; clients split anything larger.
|
||||
the smallest such thing: a WebSocket server that passes messages among
|
||||
the members of a session. What a user calls a session, the relay calls a
|
||||
*room*: the word appears in the relay's code and log and in the address a
|
||||
client connects to, `wss://<server>/relay/room/<room id>`, and nowhere
|
||||
else. The relay gives each connection a number, tells the others that a
|
||||
peer has arrived, and from then on sends every message it receives from
|
||||
one member to all the others, stamped with the sender's number. When
|
||||
the last member leaves, nothing of the session remains at the relay. It
|
||||
holds at most 32 members per session and 500 sessions, and refuses
|
||||
messages over 1 MB; clients split anything larger.
|
||||
|
||||
## Sessions and encryption
|
||||
|
||||
@@ -53,7 +56,7 @@ The invitation is
|
||||
|
||||
The *secret* is 16 random bytes, made by the host's browser. From it
|
||||
every client derives two values with HKDF-SHA-256: the *room id*, which
|
||||
names the room at the relay, and the *message key*, a 256-bit AES-GCM
|
||||
names the session at the relay, and the *message key*, a 256-bit AES-GCM
|
||||
key with which every message is encrypted before it is sent and
|
||||
decrypted on arrival. The relay sees the room id, the members' network
|
||||
addresses, and the size and timing of encrypted messages. It cannot
|
||||
@@ -66,7 +69,21 @@ A link invitation wraps the same text:
|
||||
https://<site>/#join=<invitation>
|
||||
|
||||
Browsers never send the part of an address after `#` to the site, so the
|
||||
secret stays between the host and the guests.
|
||||
secret stays between the host and the guests. The Session window also
|
||||
shows the link as a QR code, so that a phone or a tablet in the room can
|
||||
join by camera; the encoder is Kokkoja's own (`qr_code.js`: byte mode,
|
||||
error correction level M, any version), checked by the tests against
|
||||
Nayuki's reference encoder.
|
||||
|
||||
The client writes its singular events (pages, images, the connection,
|
||||
the co-host right, the first input report) to the browser's console
|
||||
and keeps them, with a trace of every press, release and cancellation
|
||||
of the pointer (an eraser's release says how many strokes and text
|
||||
blocks it removed), every change of tool and the touch events, in
|
||||
memory (`log.js`, the last 400 entries). The Session window shows the record with a Copy button,
|
||||
so that a guest on a tablet, where there is no console, can send it
|
||||
when the pen misbehaves. The record stays in the browser tab; nothing
|
||||
of it is sent anywhere by Kokkoja.
|
||||
|
||||
## Identity and layers
|
||||
|
||||
@@ -74,7 +91,7 @@ Each participant has a signing key pair (ECDSA on P-256), made in the
|
||||
browser the first time and then kept, by the local program in its
|
||||
configuration directory or by the browser in its own storage. The
|
||||
*participant id* is the first 16 bytes of the SHA-256 hash of the public
|
||||
key. When a client joins a room it announces itself with a signed
|
||||
key. When a client connects to a session it announces itself with a signed
|
||||
`hello` carrying its name and public key; the signature covers the room
|
||||
id and the peer number the relay stamped on the message, so nobody can
|
||||
replay it elsewhere or claim another peer's connection. Until a peer has
|
||||
@@ -89,23 +106,37 @@ kept, a person is the same participant in every session from the same
|
||||
computer, and their writing on a page loaded weeks later is still theirs.
|
||||
|
||||
The host is whoever holds the key whose id is in the invitation. Pages,
|
||||
images and the list of guests allowed to start pages are accepted only
|
||||
images and the list of co-hosts are accepted only
|
||||
from the host (or from an allowed guest, for pages and images).
|
||||
|
||||
## Pages
|
||||
|
||||
Page coordinates are in units of 0.1 mm. A blank page is an A4 sheet,
|
||||
2100 by 2970 units. Writing within 8 mm of an edge grows the sheet by
|
||||
8 mm on that side. An image is placed at its natural size, taken from
|
||||
Page coordinates are in units of 0.1 mm. A blank page is an A4 sheet
|
||||
in landscape, 2970 by 2100 units. "Widen" makes the sheet wider, and
|
||||
"Shrink" makes it the bounding box of everything on the page plus the
|
||||
greater of the two margins, exactly, on every side; both are changes to the page like adding
|
||||
an image, carried in the page descriptor (its `left` and `top` edges and
|
||||
its size) with the images' revision raised. Writing within 5 mm of an edge grows the page by
|
||||
5 mm on that side, counted from the sheet's edge. An image is placed at its natural size, taken from
|
||||
the resolution recorded in the file, or 0.1 mm per pixel when there is
|
||||
none, centred across the sheet, 8 mm from the top or from the image
|
||||
above, scaled down if wider than the sheet inside its margins (or, if the
|
||||
person adding it chooses, placed at natural size with the sheet widened
|
||||
to hold it). A page holds at most 12 images and 24 MB of image data.
|
||||
none (the nominal 72 and 96 dpi that cameras and screenshots write count
|
||||
as none), centred across the page, 5 mm from the top or from the image
|
||||
above, the sheet widened equally on both sides if it is wider than the
|
||||
page; only one wider than a page can be, 2 m, is scaled down. A page holds at most 12 images and 24 MB of image data.
|
||||
An image file over 2400 pixels on a side or 1.5 MB, or not PNG or JPEG,
|
||||
is redrawn at most 2400 pixels and stored as JPEG before it is shared;
|
||||
smaller PNG and JPEG files are shared byte for byte.
|
||||
|
||||
A text block is free text, or a *text rectangle* with a width and a
|
||||
height, drawn with a red frame on a white ground; the ground is drawn
|
||||
beneath every layer, so that it hides an image and never anyone's
|
||||
writing, and the frame within the owner's layer. A *Hide* rectangle is
|
||||
a page object like an image, in the page descriptor and the page file,
|
||||
drawn white above every layer with blue corners on screen; made, moved
|
||||
and removed by the host and co-hosts. Both are moved by a hold of
|
||||
the pen and resized from their corners, like images but with their
|
||||
shape free; an image keeps its shape.
|
||||
|
||||
A stroke is a list of points with pressure, and the line width is a
|
||||
function of pressure: nominal at a pressure of 0.4, about 2.6 times that
|
||||
at 0.75. Points are sent while the stroke is drawn, so the others see it
|
||||
@@ -127,7 +158,7 @@ it, rewritten a moment after every change (at most every 400 ms while
|
||||
writing continues, at least every 2 s). A *kept* page is a copy of
|
||||
`Current.svg` named `YYYY_MM_DD_NN.svg`, the day being when the page was
|
||||
last changed and NN a serial number within that day. A copy is made when
|
||||
the user asks (**Keep page**), and by the program whenever `Current.svg`
|
||||
the user asks (**Keep**), and by the program whenever `Current.svg`
|
||||
is about to be given to another page: when the session moves to a new
|
||||
page, when the notebook is changed, and when a session begins and finds
|
||||
a page of another session in the notebook. Nothing is copied if the
|
||||
@@ -213,7 +244,7 @@ computer behind a home router is not without arrangement.
|
||||
|
||||
The client uses the browser's pointer events, which deliver every sample
|
||||
a pen produces, with pressure, in Firefox and in Chromium-based browsers
|
||||
on Linux and macOS. The panel's last line shows what arrives. When a
|
||||
on Linux and macOS. The browser's console shows what arrives. When a
|
||||
pen has been used, touches are ignored, so a hand resting on a touch
|
||||
screen does not draw; this rule has not yet been tested with a device
|
||||
that has both a pen and a touch sensor. Kokkoja opens none of the
|
||||
@@ -221,6 +252,23 @@ browser's system dialogs (the colour palette and, with the local
|
||||
program, the file chooser are its own), because one such dialog crashed
|
||||
Firefox on Linux.
|
||||
|
||||
## Adjustable choices
|
||||
|
||||
Some choices of the interface are named constants at the top of the
|
||||
file that uses them, so that they can be changed in one place, or offered
|
||||
as preferences later: the line widths and the five colours (`main.js`),
|
||||
the zoom step of the wheel and the zoom per 100 pixels of a pen drag
|
||||
(`renderer.js`), the dead zone of that drag (`pen_input.js`), the margin
|
||||
by which the page grows (`page_model.js`), the tooltip delay
|
||||
(`tooltip.js`), the hold that moves an image (600 ms, with 6 pixels of
|
||||
slack, `pen_input.js`), the reach of an image's corner (24 pixels,
|
||||
`renderer.js`), the smallest an image can be scaled to (1 cm,
|
||||
`page_model.js`), how often a dragged image's place is sent (40 ms,
|
||||
`session.js`) and the points of a stroke (25 ms, `session.js`), the colour and width of a text rectangle's frame
|
||||
(`page_file.js`) and whether the frame is shown whole or as corners on
|
||||
screen (`TEXT_FRAME_STYLE` in `renderer.js`; the file and the export
|
||||
always hold the whole frame).
|
||||
|
||||
## Development
|
||||
|
||||
The code is Python and JavaScript only. The tests run with
|
||||
|
||||
+50
-5
@@ -33,7 +33,7 @@ layer of its own. You can erase your own writing and nothing else; nobody
|
||||
else can erase yours. Any layer can be hidden on your own screen without
|
||||
affecting anyone else's view.
|
||||
|
||||
**A page that grows.** A page is an A4 sheet. When writing approaches an
|
||||
**A page that grows.** A page is an A4 sheet, lying on its side. When writing approaches an
|
||||
edge, the sheet grows in that direction, so you are never short of room.
|
||||
An image is placed at its natural size; one wider than the sheet is
|
||||
scaled down to fit, and the sheet grows downward to hold further images.
|
||||
@@ -62,8 +62,9 @@ host runs Kokkoja.
|
||||
|
||||
**Free software.** Kokkoja is free and open-source. Anyone can use it
|
||||
without paying, and nobody depends on a company's service. It runs in
|
||||
Firefox and in browsers built on the Chromium engine, such as Brave and
|
||||
Chrome, on Linux and macOS.
|
||||
Firefox, in browsers built on the Chromium engine, such as Brave or
|
||||
Chrome, and in Safari, on Linux and macOS; a guest can also join from
|
||||
Safari on an iPad or an iPhone, writing with a pencil or a finger.
|
||||
|
||||
## Who uses it
|
||||
|
||||
@@ -93,8 +94,52 @@ A session has one *host*, the person who starts it, and any number of
|
||||
guests. The host sends the guests an invitation, by email, in a chat
|
||||
message, or by any other means. The host *drives*: only the host puts
|
||||
images on the page, starts new pages or loads pages from a notebook, and
|
||||
everyone follows. The host can give any guest the same abilities, for a
|
||||
discussion among colleagues.
|
||||
everyone follows. The host can make any guest a *co-host*, with the
|
||||
same powers, for a discussion among colleagues.
|
||||
|
||||
## What runs where
|
||||
|
||||
Three kinds of machine take part, and it helps to have the picture in
|
||||
mind before reading on.
|
||||
|
||||
```
|
||||
Host's computer Server Guests
|
||||
--------------- ------ ------
|
||||
Kokkoja program kokkoja.andykopra.com Guest A: a browser
|
||||
serves the client -+ | opens the link
|
||||
to the browser at | +----+-----+ the server serves
|
||||
localhost:8760 | | relay | <-------------> the client to it;
|
||||
keeps the notebook | | (passes | notebook in the
|
||||
as files | | messages,| browser, downloads
|
||||
| | | reads |
|
||||
browser <-----------+ | nothing) | <-------------> Guest B: has the
|
||||
| +----------+ Kokkoja program too;
|
||||
+---- encrypted ----------^ | joins from its own
|
||||
messages | start screen; note-
|
||||
web site: book as files
|
||||
the client's files
|
||||
```
|
||||
|
||||
* **The host** runs the small Kokkoja program on their own computer.
|
||||
It shows Kokkoja in the host's browser, at the address
|
||||
`http://localhost:8760/`, and it keeps the host's notebooks as
|
||||
directories of files. It must be running for as long as the host is
|
||||
in a session; the browser alone cannot reach the notebooks.
|
||||
|
||||
* **The server** does two things for everyone. Its *relay* passes the
|
||||
participants' messages, which are encrypted before they leave each
|
||||
computer, so the relay reads nothing. Its *web site* serves the
|
||||
Kokkoja client to guests who join by link. The host's program is
|
||||
told the server's address once, when it is started.
|
||||
|
||||
* **A guest** needs only a browser: opening the invitation link fetches
|
||||
the client from the server's web site, and the guest's notebook lives
|
||||
in that browser, with kept pages and exports offered as downloads. A
|
||||
guest who wants a notebook of real files runs the Kokkoja program as
|
||||
the host does, and joins from the program's own start screen.
|
||||
|
||||
Every participant's computer holds the whole page. Only changes travel,
|
||||
through the relay, to everyone else. Nothing is stored on the server.
|
||||
|
||||
The rest of this documentation describes Kokkoja from the guest's point of
|
||||
view first, since the host sees the same screen and has a few more
|
||||
|
||||
Reference in new issue
Block a user