Merge pull request 'brand: Ratatoskr replaces Cinny branding (do not merge)' (#11) from void/brand into main
20
index.html
|
|
@ -4,21 +4,17 @@
|
|||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
|
||||
<title>Cinny</title>
|
||||
<meta name="name" content="Cinny" />
|
||||
<meta name="author" content="Ajay Bura" />
|
||||
<title>Ratatoskr</title>
|
||||
<meta name="name" content="Ratatoskr" />
|
||||
<meta name="author" content="GameCult" />
|
||||
<meta
|
||||
name="description"
|
||||
content="A Matrix client where you can enjoy the conversation using simple, elegant and secure interface protected by e2ee with the power of open source."
|
||||
/>
|
||||
<meta
|
||||
name="keywords"
|
||||
content="cinny, cinnyapp, cinnychat, matrix, matrix client, matrix.org, element"
|
||||
/>
|
||||
<meta name="keywords" content="ratatoskr, gamecult, matrix, matrix client, matrix.org" />
|
||||
|
||||
<meta property="og:title" content="Cinny" />
|
||||
<meta property="og:url" content="https://cinny.in" />
|
||||
<meta property="og:image" content="https://cinny.in/assets/favicon-48x48.png" />
|
||||
<meta property="og:title" content="Ratatoskr" />
|
||||
<meta property="og:url" content="https://gamecult.org" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="A Matrix client where you can enjoy the conversation using simple, elegant and secure interface protected by e2ee with the power of open source."
|
||||
|
|
@ -29,8 +25,8 @@
|
|||
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="application-name" content="Cinny" />
|
||||
<meta name="apple-mobile-web-app-title" content="Cinny" />
|
||||
<meta name="application-name" content="Ratatoskr" />
|
||||
<meta name="apple-mobile-web-app-title" content="Ratatoskr" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 2.3 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "Cinny",
|
||||
"short_name": "Cinny",
|
||||
"description": "Yet another matrix client",
|
||||
"name": "Ratatoskr",
|
||||
"short_name": "Ratatoskr",
|
||||
"description": "GameCult's Matrix client",
|
||||
"dir": "auto",
|
||||
"lang": "en-US",
|
||||
"display": "standalone",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 3 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 4 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 817 B |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 3 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.6 KiB |
|
|
@ -1,13 +0,0 @@
|
|||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_2707_1961)">
|
||||
<path d="M10.5867 17.3522C10.0727 17.4492 9.54226 17.5 9 17.5C4.30558 17.5 0.5 13.6944 0.5 9C0.5 4.30558 4.30558 0.5 9 0.5C13.6944 0.5 17.5 4.30558 17.5 9C17.5 9.54226 17.4492 10.0727 17.3522 10.5867C16.6511 10.2123 15.8503 10 15 10C12.2386 10 10 12.2386 10 15C10 15.8503 10.2123 16.6511 10.5867 17.3522Z" fill="white"/>
|
||||
<path d="M10 6.39999C10 6.67614 9.77614 6.89999 9.5 6.89999C9.22386 6.89999 9 6.67614 9 6.39999C9 6.12385 9.22386 5.89999 9.5 5.89999C9.77614 5.89999 10 6.12385 10 6.39999Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 0C4 0 0 4 0 9C0 14 4 18 9 18C9.63967 18 10.263 17.9345 10.8636 17.8099C10.3186 17.0091 10 16.0417 10 15C10 12.2386 12.2386 10 15 10C16.0417 10 17.0091 10.3186 17.8099 10.8636C17.9345 10.263 18 9.63967 18 9C18 4 14 0 9 0ZM1.2 10.8L4.7 8.5V8.2C4.7 6.4 6 5 7.8 4.8H8.2C9.4 4.8 10.5 5.4 11.1 6.4C11.4 6.3 11.7 6.3 12 6.3C12.4 6.3 12.8 6.3 13.2 6.4C13.9 6.6 14.6 6.9 15.2 7.3C14.6 7.1 14 7 13.3 7C12.1 7 11.1 7.4 10.4 8.4C9.7 9.3 9.3 10.4 9.3 11.6C9.3 13.1 8.9 14.5 8 15.8C7.93744 15.8834 7.87923 15.9625 7.82356 16.0381C7.6123 16.325 7.43739 16.5626 7.2 16.8C4.2 16.1 1.9 13.8 1.2 10.8Z" fill="black"/>
|
||||
<path d="M18 15C18 16.6569 16.6569 18 15 18C13.3431 18 12 16.6569 12 15C12 13.3431 13.3431 12 15 12C16.6569 12 18 13.3431 18 15Z" fill="#45B83B"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_2707_1961">
|
||||
<rect width="18" height="18" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
|
|
@ -1,13 +0,0 @@
|
|||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_2707_2015)">
|
||||
<path d="M10.5867 17.3522C10.0727 17.4492 9.54226 17.5 9 17.5C4.30558 17.5 0.5 13.6944 0.5 9C0.5 4.30558 4.30558 0.5 9 0.5C13.6944 0.5 17.5 4.30558 17.5 9C17.5 9.54226 17.4492 10.0727 17.3522 10.5867C16.6511 10.2123 15.8503 10 15 10C12.2386 10 10 12.2386 10 15C10 15.8503 10.2123 16.6511 10.5867 17.3522Z" fill="white"/>
|
||||
<path d="M10 6.39999C10 6.67614 9.77614 6.89999 9.5 6.89999C9.22386 6.89999 9 6.67614 9 6.39999C9 6.12385 9.22386 5.89999 9.5 5.89999C9.77614 5.89999 10 6.12385 10 6.39999Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 0C4 0 0 4 0 9C0 14 4 18 9 18C9.63967 18 10.263 17.9345 10.8636 17.8099C10.3186 17.0091 10 16.0417 10 15C10 12.2386 12.2386 10 15 10C16.0417 10 17.0091 10.3186 17.8099 10.8636C17.9345 10.263 18 9.63967 18 9C18 4 14 0 9 0ZM1.2 10.8L4.7 8.5V8.2C4.7 6.4 6 5 7.8 4.8H8.2C9.4 4.8 10.5 5.4 11.1 6.4C11.4 6.3 11.7 6.3 12 6.3C12.4 6.3 12.8 6.3 13.2 6.4C13.9 6.6 14.6 6.9 15.2 7.3C14.6 7.1 14 7 13.3 7C12.1 7 11.1 7.4 10.4 8.4C9.7 9.3 9.3 10.4 9.3 11.6C9.3 13.1 8.9 14.5 8 15.8C7.93744 15.8834 7.87923 15.9625 7.82356 16.0381C7.6123 16.325 7.43739 16.5626 7.2 16.8C4.2 16.1 1.9 13.8 1.2 10.8Z" fill="black"/>
|
||||
<path d="M18 15C18 16.6569 16.6569 18 15 18C13.3431 18 12 16.6569 12 15C12 13.3431 13.3431 12 15 12C16.6569 12 18 13.3431 18 15Z" fill="#989898"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_2707_2015">
|
||||
<rect width="18" height="18" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
|
|
@ -1,19 +0,0 @@
|
|||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In -->
|
||||
<svg version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
|
||||
x="0px" y="0px" width="18px" height="18px" viewBox="0 0 18 18" enable-background="new 0 0 18 18" xml:space="preserve">
|
||||
<defs>
|
||||
</defs>
|
||||
<g>
|
||||
<g>
|
||||
<circle fill="#FFFFFF" cx="9" cy="9" r="8.5"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M9,0C4,0,0,4,0,9c0,5,4,9,9,9c5,0,9-4,9-9C18,4,14,0,9,0z M1.2,10.8l3.5-2.3c0-0.1,0-0.2,0-0.3c0-1.8,1.3-3.2,3.1-3.4
|
||||
c0.1,0,0.2,0,0.4,0c1.2,0,2.3,0.6,2.9,1.6c0.3-0.1,0.6-0.1,0.9-0.1c0.4,0,0.8,0,1.2,0.1c0.7,0.2,1.4,0.5,2,0.9
|
||||
C14.6,7.1,14,7,13.3,7c-1.2,0-2.2,0.4-2.9,1.4c-0.7,0.9-1.1,2-1.1,3.2c0,1.5-0.4,2.9-1.3,4.2c-0.3,0.4-0.5,0.7-0.8,1
|
||||
C4.2,16.1,1.9,13.8,1.2,10.8z"/>
|
||||
<circle cx="9.5" cy="6.4" r="0.5"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 871 B |
17
public/res/svg/ratatoskr-highlight.svg
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
|
||||
<ellipse cx="19" cy="33" rx="13" ry="22" transform="rotate(-15 19 33)" fill="#d9742b"/>
|
||||
<ellipse cx="21" cy="33" rx="7" ry="15" transform="rotate(-15 21 33)" fill="#f0a45d"/>
|
||||
<ellipse cx="36" cy="43" rx="11" ry="14" transform="rotate(0 36 43)" fill="#e0833a"/>
|
||||
<ellipse cx="40" cy="46" rx="6" ry="9" transform="rotate(0 40 46)" fill="#f6dcb8"/>
|
||||
<polygon points="35,19 36,7 43,15" fill="#c9672a"/>
|
||||
<polygon points="44,15 50,7 52,19" fill="#c9672a"/>
|
||||
<circle cx="43" cy="25" r="10" fill="#e0833a"/>
|
||||
<ellipse cx="47" cy="29" rx="5" ry="3.5" transform="rotate(0 47 29)" fill="#f6dcb8"/>
|
||||
<circle cx="46.5" cy="23.5" r="1.8" fill="#1a1a1a"/>
|
||||
<circle cx="47" cy="23" r="0.6" fill="#ffffff"/>
|
||||
<circle cx="52" cy="27.5" r="1.5" fill="#1a1a1a"/>
|
||||
<ellipse cx="33" cy="56" rx="5" ry="2.5" transform="rotate(0 33 56)" fill="#c9672a"/>
|
||||
<ellipse cx="44" cy="56" rx="4.5" ry="2.5" transform="rotate(0 44 56)" fill="#c9672a"/>
|
||||
<circle cx="52" cy="52" r="11" fill="#ffffff"/>
|
||||
<circle cx="52" cy="52" r="8" fill="#45B83B"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
17
public/res/svg/ratatoskr-unread.svg
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
|
||||
<ellipse cx="19" cy="33" rx="13" ry="22" transform="rotate(-15 19 33)" fill="#d9742b"/>
|
||||
<ellipse cx="21" cy="33" rx="7" ry="15" transform="rotate(-15 21 33)" fill="#f0a45d"/>
|
||||
<ellipse cx="36" cy="43" rx="11" ry="14" transform="rotate(0 36 43)" fill="#e0833a"/>
|
||||
<ellipse cx="40" cy="46" rx="6" ry="9" transform="rotate(0 40 46)" fill="#f6dcb8"/>
|
||||
<polygon points="35,19 36,7 43,15" fill="#c9672a"/>
|
||||
<polygon points="44,15 50,7 52,19" fill="#c9672a"/>
|
||||
<circle cx="43" cy="25" r="10" fill="#e0833a"/>
|
||||
<ellipse cx="47" cy="29" rx="5" ry="3.5" transform="rotate(0 47 29)" fill="#f6dcb8"/>
|
||||
<circle cx="46.5" cy="23.5" r="1.8" fill="#1a1a1a"/>
|
||||
<circle cx="47" cy="23" r="0.6" fill="#ffffff"/>
|
||||
<circle cx="52" cy="27.5" r="1.5" fill="#1a1a1a"/>
|
||||
<ellipse cx="33" cy="56" rx="5" ry="2.5" transform="rotate(0 33 56)" fill="#c9672a"/>
|
||||
<ellipse cx="44" cy="56" rx="4.5" ry="2.5" transform="rotate(0 44 56)" fill="#c9672a"/>
|
||||
<circle cx="52" cy="52" r="11" fill="#ffffff"/>
|
||||
<circle cx="52" cy="52" r="8" fill="#989898"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
15
public/res/svg/ratatoskr.svg
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
|
||||
<ellipse cx="19" cy="33" rx="13" ry="22" transform="rotate(-15 19 33)" fill="#d9742b"/>
|
||||
<ellipse cx="21" cy="33" rx="7" ry="15" transform="rotate(-15 21 33)" fill="#f0a45d"/>
|
||||
<ellipse cx="36" cy="43" rx="11" ry="14" transform="rotate(0 36 43)" fill="#e0833a"/>
|
||||
<ellipse cx="40" cy="46" rx="6" ry="9" transform="rotate(0 40 46)" fill="#f6dcb8"/>
|
||||
<polygon points="35,19 36,7 43,15" fill="#c9672a"/>
|
||||
<polygon points="44,15 50,7 52,19" fill="#c9672a"/>
|
||||
<circle cx="43" cy="25" r="10" fill="#e0833a"/>
|
||||
<ellipse cx="47" cy="29" rx="5" ry="3.5" transform="rotate(0 47 29)" fill="#f6dcb8"/>
|
||||
<circle cx="46.5" cy="23.5" r="1.8" fill="#1a1a1a"/>
|
||||
<circle cx="47" cy="23" r="0.6" fill="#ffffff"/>
|
||||
<circle cx="52" cy="27.5" r="1.5" fill="#1a1a1a"/>
|
||||
<ellipse cx="33" cy="56" rx="5" ry="2.5" transform="rotate(0 33 56)" fill="#c9672a"/>
|
||||
<ellipse cx="44" cy="56" rx="4.5" ry="2.5" transform="rotate(0 44 56)" fill="#c9672a"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1,001 B |
202
scripts/gen-brand.mjs
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
// Draws the Ratatoskr squirrel once, as shapes, and writes the SVG logos plus the
|
||||
// favicon and app-icon PNGs from the same shapes (no image tools needed).
|
||||
// Run: node scripts/gen-brand.mjs
|
||||
import { deflateSync } from 'node:zlib';
|
||||
import { mkdirSync, writeFileSync } from 'node:fs';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const root = join(dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const BG = '#1c1b22';
|
||||
|
||||
// Squirrel facing right on a 64x64 grid. Later shapes draw over earlier ones.
|
||||
const squirrel = [
|
||||
{ t: 'ellipse', cx: 19, cy: 33, rx: 13, ry: 22, rot: -15, fill: '#d9742b' },
|
||||
{ t: 'ellipse', cx: 21, cy: 33, rx: 7, ry: 15, rot: -15, fill: '#f0a45d' },
|
||||
{ t: 'ellipse', cx: 36, cy: 43, rx: 11, ry: 14, rot: 0, fill: '#e0833a' },
|
||||
{ t: 'ellipse', cx: 40, cy: 46, rx: 6, ry: 9, rot: 0, fill: '#f6dcb8' },
|
||||
{
|
||||
t: 'poly',
|
||||
pts: [
|
||||
[35, 19],
|
||||
[36, 7],
|
||||
[43, 15],
|
||||
],
|
||||
fill: '#c9672a',
|
||||
},
|
||||
{
|
||||
t: 'poly',
|
||||
pts: [
|
||||
[44, 15],
|
||||
[50, 7],
|
||||
[52, 19],
|
||||
],
|
||||
fill: '#c9672a',
|
||||
},
|
||||
{ t: 'circle', cx: 43, cy: 25, r: 10, fill: '#e0833a' },
|
||||
{ t: 'ellipse', cx: 47, cy: 29, rx: 5, ry: 3.5, rot: 0, fill: '#f6dcb8' },
|
||||
{ t: 'circle', cx: 46.5, cy: 23.5, r: 1.8, fill: '#1a1a1a' },
|
||||
{ t: 'circle', cx: 47, cy: 23, r: 0.6, fill: '#ffffff' },
|
||||
{ t: 'circle', cx: 52, cy: 27.5, r: 1.5, fill: '#1a1a1a' },
|
||||
{ t: 'ellipse', cx: 33, cy: 56, rx: 5, ry: 2.5, rot: 0, fill: '#c9672a' },
|
||||
{ t: 'ellipse', cx: 44, cy: 56, rx: 4.5, ry: 2.5, rot: 0, fill: '#c9672a' },
|
||||
];
|
||||
const badge = (fill) => [
|
||||
{ t: 'circle', cx: 52, cy: 52, r: 11, fill: '#ffffff' },
|
||||
{ t: 'circle', cx: 52, cy: 52, r: 8, fill },
|
||||
];
|
||||
const background = [{ t: 'rect', x: 0, y: 0, w: 64, h: 64, fill: BG }];
|
||||
|
||||
const f = (n) => +n.toFixed(2);
|
||||
const svgOf = (shapes) =>
|
||||
shapes
|
||||
.map((s) => {
|
||||
if (s.t === 'circle')
|
||||
return `<circle cx="${s.cx}" cy="${s.cy}" r="${s.r}" fill="${s.fill}"/>`;
|
||||
if (s.t === 'rect') return `<rect width="${s.w}" height="${s.h}" fill="${s.fill}"/>`;
|
||||
if (s.t === 'poly')
|
||||
return `<polygon points="${s.pts.map((p) => p.join(',')).join(' ')}" fill="${s.fill}"/>`;
|
||||
return `<ellipse cx="${s.cx}" cy="${s.cy}" rx="${s.rx}" ry="${s.ry}" transform="rotate(${s.rot} ${s.cx} ${s.cy})" fill="${s.fill}"/>`;
|
||||
})
|
||||
.join('\n');
|
||||
const writeSvg = (name, shapes) =>
|
||||
writeFileSync(
|
||||
join(root, 'public/res/svg', name),
|
||||
`<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">\n${svgOf(
|
||||
shapes
|
||||
)}\n</svg>\n`
|
||||
);
|
||||
|
||||
const hex = (h) => [1, 3, 5].map((i) => parseInt(h.slice(i, i + 2), 16));
|
||||
const inside = (s, x, y) => {
|
||||
if (s.t === 'rect') return x >= s.x && x < s.x + s.w && y >= s.y && y < s.y + s.h;
|
||||
if (s.t === 'circle') return (x - s.cx) ** 2 + (y - s.cy) ** 2 <= s.r ** 2;
|
||||
if (s.t === 'ellipse') {
|
||||
const a = (-s.rot * Math.PI) / 180;
|
||||
const dx = x - s.cx;
|
||||
const dy = y - s.cy;
|
||||
const u = dx * Math.cos(a) - dy * Math.sin(a);
|
||||
const v = dx * Math.sin(a) + dy * Math.cos(a);
|
||||
return (u / s.rx) ** 2 + (v / s.ry) ** 2 <= 1;
|
||||
}
|
||||
let c = false;
|
||||
for (let i = 0, j = s.pts.length - 1; i < s.pts.length; j = i++) {
|
||||
const [xi, yi] = s.pts[i];
|
||||
const [xj, yj] = s.pts[j];
|
||||
if (yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi) c = !c;
|
||||
}
|
||||
return c;
|
||||
};
|
||||
|
||||
const crcTable = Array.from({ length: 256 }, (_, n) => {
|
||||
let c = n;
|
||||
for (let k = 0; k < 8; k += 1) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
||||
return c >>> 0;
|
||||
});
|
||||
const crc = (b) => {
|
||||
let c = 0xffffffff;
|
||||
for (const x of b) c = crcTable[(c ^ x) & 255] ^ (c >>> 8);
|
||||
return (c ^ 0xffffffff) >>> 0;
|
||||
};
|
||||
const chunk = (type, data) => {
|
||||
const out = Buffer.alloc(12 + data.length);
|
||||
out.writeUInt32BE(data.length, 0);
|
||||
out.write(type, 4, 'ascii');
|
||||
data.copy(out, 8);
|
||||
out.writeUInt32BE(crc(out.subarray(4, 8 + data.length)), 8 + data.length);
|
||||
return out;
|
||||
};
|
||||
|
||||
// Rasterise with 4x4 supersampling; `scale` shrinks the drawing about the centre.
|
||||
const png = (shapes, size, scale = 1) => {
|
||||
const rgba = Buffer.alloc(size * size * 4);
|
||||
const SS = 4;
|
||||
const colours = shapes.map((s) => hex(s.fill));
|
||||
for (let py = 0; py < size; py += 1) {
|
||||
for (let px = 0; px < size; px += 1) {
|
||||
let r = 0;
|
||||
let g = 0;
|
||||
let b = 0;
|
||||
let a = 0;
|
||||
for (let sy = 0; sy < SS; sy += 1) {
|
||||
for (let sx = 0; sx < SS; sx += 1) {
|
||||
const gx = ((px + (sx + 0.5) / SS) / size) * 64;
|
||||
const gy = ((py + (sy + 0.5) / SS) / size) * 64;
|
||||
// the background rect covers the whole canvas and ignores `scale`
|
||||
let hit = -1;
|
||||
shapes.forEach((s, i) => {
|
||||
const x = s.t === 'rect' ? gx : (gx - 32) / scale + 32;
|
||||
const y = s.t === 'rect' ? gy : (gy - 32) / scale + 32;
|
||||
if (inside(s, x, y)) hit = i;
|
||||
});
|
||||
if (hit >= 0) {
|
||||
[r, g, b] = [r + colours[hit][0], g + colours[hit][1], b + colours[hit][2]];
|
||||
a += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
const o = (py * size + px) * 4;
|
||||
if (a > 0) {
|
||||
rgba[o] = Math.round(r / a);
|
||||
rgba[o + 1] = Math.round(g / a);
|
||||
rgba[o + 2] = Math.round(b / a);
|
||||
}
|
||||
rgba[o + 3] = Math.round((a / (SS * SS)) * 255);
|
||||
}
|
||||
}
|
||||
const raw = Buffer.alloc(size * (size * 4 + 1));
|
||||
for (let y = 0; y < size; y += 1) {
|
||||
raw[y * (size * 4 + 1)] = 0;
|
||||
rgba.copy(raw, y * (size * 4 + 1) + 1, y * size * 4, (y + 1) * size * 4);
|
||||
}
|
||||
const ihdr = Buffer.alloc(13);
|
||||
ihdr.writeUInt32BE(size, 0);
|
||||
ihdr.writeUInt32BE(size, 4);
|
||||
ihdr.set([8, 6, 0, 0, 0], 8);
|
||||
return Buffer.concat([
|
||||
Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]),
|
||||
chunk('IHDR', ihdr),
|
||||
chunk('IDAT', deflateSync(raw)),
|
||||
chunk('IEND', Buffer.alloc(0)),
|
||||
]);
|
||||
};
|
||||
|
||||
// ICO container holding PNG images.
|
||||
const ico = (images) => {
|
||||
const head = Buffer.alloc(6 + images.length * 16);
|
||||
head.writeUInt16LE(1, 2);
|
||||
head.writeUInt16LE(images.length, 4);
|
||||
let offset = head.length;
|
||||
images.forEach(({ size, data }, i) => {
|
||||
const e = 6 + i * 16;
|
||||
head[e] = size;
|
||||
head[e + 1] = size;
|
||||
head.writeUInt16LE(1, e + 4);
|
||||
head.writeUInt16LE(32, e + 6);
|
||||
head.writeUInt32LE(data.length, e + 8);
|
||||
head.writeUInt32LE(offset, e + 12);
|
||||
offset += data.length;
|
||||
});
|
||||
return Buffer.concat([head, ...images.map((i) => i.data)]);
|
||||
};
|
||||
|
||||
writeSvg('ratatoskr.svg', squirrel);
|
||||
writeSvg('ratatoskr-unread.svg', [...squirrel, ...badge('#989898')]);
|
||||
writeSvg('ratatoskr-highlight.svg', [...squirrel, ...badge('#45B83B')]);
|
||||
|
||||
const icon = [...background, ...squirrel];
|
||||
const put = (dir, name, size) => {
|
||||
mkdirSync(join(root, 'public/res', dir), { recursive: true });
|
||||
writeFileSync(join(root, 'public/res', dir, name), png(icon, size, 0.82));
|
||||
};
|
||||
[36, 48, 72, 96, 144, 192, 256, 384, 512].forEach((s) =>
|
||||
put('android', `android-chrome-${s}x${s}.png`, s)
|
||||
);
|
||||
[57, 60, 72, 76, 114, 120, 144, 152, 167, 180].forEach((s) =>
|
||||
put('apple', `apple-touch-icon-${s}x${s}.png`, s)
|
||||
);
|
||||
writeFileSync(
|
||||
join(root, 'public/favicon.ico'),
|
||||
ico([16, 32, 48].map((size) => ({ size, data: png(icon, size, 0.9) })))
|
||||
);
|
||||
console.log('wrote svg logos, favicon.ico, android and apple icons');
|
||||
|
|
@ -21,7 +21,7 @@ export function SplashScreen({ children }: SplashScreenProps) {
|
|||
justifyContent="Center"
|
||||
>
|
||||
<Text size="H2" align="Center">
|
||||
Cinny
|
||||
Ratatoskr
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Page, PageContent, PageHeader } from '../../../components/page';
|
|||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
import { SequenceCardStyle } from '../styles.css';
|
||||
import { SettingTile } from '../../../components/setting-tile';
|
||||
import CinnySVG from '../../../../../public/res/svg/cinny.svg';
|
||||
import RatatoskrSVG from '../../../../../public/res/svg/ratatoskr.svg';
|
||||
import { clearCacheAndReload } from '../../../../client/initMatrix';
|
||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||
|
||||
|
|
@ -38,23 +38,23 @@ export function About({ requestClose }: AboutProps) {
|
|||
<Box shrink="No">
|
||||
<img
|
||||
style={{ width: toRem(60), height: toRem(60) }}
|
||||
src={CinnySVG}
|
||||
alt="Cinny logo"
|
||||
src={RatatoskrSVG}
|
||||
alt="Ratatoskr logo"
|
||||
/>
|
||||
</Box>
|
||||
<Box direction="Column" gap="300">
|
||||
<Box direction="Column" gap="100">
|
||||
<Box gap="100" alignItems="End">
|
||||
<Text size="H3">Cinny</Text>
|
||||
<Text size="H3">Ratatoskr</Text>
|
||||
<Text size="T200">v4.12.8</Text>
|
||||
</Box>
|
||||
<Text>Yet another matrix client.</Text>
|
||||
<Text>GameCult's Matrix client.</Text>
|
||||
</Box>
|
||||
|
||||
<Box gap="200" wrap="Wrap">
|
||||
<Button
|
||||
as="a"
|
||||
href="https://github.com/cinnyapp/cinny"
|
||||
href="https://eureka.gamecult.org/forge/GameCult/Ratatoskr"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
variant="Secondary"
|
||||
|
|
@ -65,20 +65,19 @@ export function About({ requestClose }: AboutProps) {
|
|||
>
|
||||
<Text size="B300">Source Code</Text>
|
||||
</Button>
|
||||
<Button
|
||||
as="a"
|
||||
href="https://cinny.in/#sponsor"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
variant="Critical"
|
||||
fill="Soft"
|
||||
size="300"
|
||||
radii="300"
|
||||
before={<Icon src={Icons.Heart} size="100" filled />}
|
||||
>
|
||||
<Text size="B300">Support</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
<Text size="T300">
|
||||
Based on{' '}
|
||||
<a
|
||||
href="https://github.com/cinnyapp/cinny"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
Cinny
|
||||
</a>{' '}
|
||||
4.12.8 by Ajay Bura and contributors. Ratatoskr is free software under the GNU
|
||||
Affero General Public License v3; its source is at the Source Code link above.
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box direction="Column" gap="100">
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ function ExportKeys() {
|
|||
const blob = new Blob([encKeys], {
|
||||
type: 'text/plain;charset=us-ascii',
|
||||
});
|
||||
FileSaver.saveAs(blob, 'cinny-keys.txt');
|
||||
FileSaver.saveAs(blob, 'ratatoskr-keys.txt');
|
||||
},
|
||||
[mx]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ function EmailNotification() {
|
|||
device_display_name: email,
|
||||
lang: 'en',
|
||||
data: {
|
||||
brand: 'Cinny',
|
||||
brand: 'Ratatoskr',
|
||||
},
|
||||
append: true,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,20 +5,26 @@ import * as css from './styles.css';
|
|||
export function AuthFooter() {
|
||||
return (
|
||||
<Box className={css.AuthFooter} justifyContent="Center" gap="400" wrap="Wrap">
|
||||
<Text as="a" size="T300" href="https://cinny.in" target="_blank" rel="noreferrer">
|
||||
<Text as="a" size="T300" href="https://gamecult.org" target="_blank" rel="noreferrer">
|
||||
About
|
||||
</Text>
|
||||
<Text
|
||||
as="a"
|
||||
size="T300"
|
||||
href="https://github.com/ajbura/cinny/releases"
|
||||
href="https://eureka.gamecult.org/forge/GameCult/Ratatoskr"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
v4.12.8
|
||||
Source
|
||||
</Text>
|
||||
<Text as="a" size="T300" href="https://twitter.com/cinnyapp" target="_blank" rel="noreferrer">
|
||||
Twitter
|
||||
<Text
|
||||
as="a"
|
||||
size="T300"
|
||||
href="https://github.com/cinnyapp/cinny"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Based on Cinny
|
||||
</Text>
|
||||
<Text as="a" size="T300" href="https://matrix.org" target="_blank" rel="noreferrer">
|
||||
Powered by Matrix
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import {
|
|||
} from '../../hooks/useClientConfig';
|
||||
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
|
||||
import { LOGIN_PATH, REGISTER_PATH, RESET_PASSWORD_PATH } from '../paths';
|
||||
import CinnySVG from '../../../../public/res/svg/cinny.svg';
|
||||
import RatatoskrSVG from '../../../../public/res/svg/ratatoskr.svg';
|
||||
import { ServerPicker } from './ServerPicker';
|
||||
import { AutoDiscoveryAction, autoDiscovery } from '../../cs-api';
|
||||
import { SpecVersionsLoader } from '../../components/SpecVersionsLoader';
|
||||
|
|
@ -134,8 +134,8 @@ export function AuthLayout() {
|
|||
<Box direction="Column" className={css.AuthCard}>
|
||||
<Header className={css.AuthHeader} size="600" variant="Surface">
|
||||
<Box grow="Yes" direction="Row" gap="300" alignItems="Center">
|
||||
<img className={css.AuthLogo} src={CinnySVG} alt="Cinny Logo" />
|
||||
<Text size="H3">Cinny</Text>
|
||||
<img className={css.AuthLogo} src={RatatoskrSVG} alt="Ratatoskr logo" />
|
||||
<Text size="H3">Ratatoskr</Text>
|
||||
</Box>
|
||||
</Header>
|
||||
<Box className={css.AuthCardContent} direction="Column">
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ export function PasswordLoginForm({ defaultUsername, defaultEmail }: PasswordLog
|
|||
user: username,
|
||||
},
|
||||
password,
|
||||
initial_device_display_name: 'Cinny Web',
|
||||
initial_device_display_name: 'Ratatoskr Web',
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ export function PasswordLoginForm({ defaultUsername, defaultEmail }: PasswordLog
|
|||
user: mxIdUsername,
|
||||
},
|
||||
password,
|
||||
initial_device_display_name: 'Cinny Web',
|
||||
initial_device_display_name: 'Ratatoskr Web',
|
||||
});
|
||||
};
|
||||
const handleEmailLogin = (email: string, password: string) => {
|
||||
|
|
@ -163,7 +163,7 @@ export function PasswordLoginForm({ defaultUsername, defaultEmail }: PasswordLog
|
|||
address: email,
|
||||
},
|
||||
password,
|
||||
initial_device_display_name: 'Cinny Web',
|
||||
initial_device_display_name: 'Ratatoskr Web',
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export function TokenLogin({ token }: TokenLoginProps) {
|
|||
startLogin(baseUrl, {
|
||||
type: 'm.login.token',
|
||||
token,
|
||||
initial_device_display_name: 'Cinny Web',
|
||||
initial_device_display_name: 'Ratatoskr Web',
|
||||
});
|
||||
}, [baseUrl, token, startLogin]);
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ function RegisterUIAFlow({
|
|||
auth: authDict,
|
||||
password,
|
||||
username,
|
||||
initial_device_display_name: 'Cinny Web',
|
||||
initial_device_display_name: 'Ratatoskr Web',
|
||||
});
|
||||
},
|
||||
[onRegister, formData]
|
||||
|
|
@ -250,7 +250,7 @@ export function PasswordRegisterForm({
|
|||
auth: {
|
||||
session: authData.session,
|
||||
},
|
||||
initial_device_display_name: 'Cinny Web',
|
||||
initial_device_display_name: 'Ratatoskr Web',
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import React, { ReactNode, useCallback, useEffect, useRef } from 'react';
|
|||
import { useNavigate } from 'react-router-dom';
|
||||
import { RoomEvent, RoomEventHandlerMap } from 'matrix-js-sdk';
|
||||
import { roomToUnreadAtom, unreadEqual, unreadInfoToUnread } from '../../state/room/roomToUnread';
|
||||
import LogoSVG from '../../../../public/res/svg/cinny.svg';
|
||||
import LogoUnreadSVG from '../../../../public/res/svg/cinny-unread.svg';
|
||||
import LogoHighlightSVG from '../../../../public/res/svg/cinny-highlight.svg';
|
||||
import LogoSVG from '../../../../public/res/svg/ratatoskr.svg';
|
||||
import LogoUnreadSVG from '../../../../public/res/svg/ratatoskr-unread.svg';
|
||||
import LogoHighlightSVG from '../../../../public/res/svg/ratatoskr-highlight.svg';
|
||||
import NotificationSound from '../../../../public/sound/notification.ogg';
|
||||
import InviteSound from '../../../../public/sound/invite.ogg';
|
||||
import { notificationPermission, setFavicon } from '../../utils/dom';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import { Box, Button, Icon, Icons, Text, config, toRem } from 'folds';
|
||||
import { Page, PageHero, PageHeroSection } from '../../components/page';
|
||||
import CinnySVG from '../../../../public/res/svg/cinny.svg';
|
||||
import RatatoskrSVG from '../../../../public/res/svg/ratatoskr.svg';
|
||||
|
||||
export function WelcomePage() {
|
||||
return (
|
||||
|
|
@ -14,17 +14,17 @@ export function WelcomePage() {
|
|||
>
|
||||
<PageHeroSection>
|
||||
<PageHero
|
||||
icon={<img width="70" height="70" src={CinnySVG} alt="Cinny Logo" />}
|
||||
title="Welcome to Cinny"
|
||||
icon={<img width="70" height="70" src={RatatoskrSVG} alt="Ratatoskr logo" />}
|
||||
title="Welcome to Ratatoskr"
|
||||
subTitle={
|
||||
<span>
|
||||
Yet another matrix client.{' '}
|
||||
GameCult's Matrix client, based on{' '}
|
||||
<a
|
||||
href="https://github.com/cinnyapp/cinny/releases"
|
||||
href="https://github.com/cinnyapp/cinny"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
v4.12.8
|
||||
Cinny
|
||||
</a>
|
||||
</span>
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ export function WelcomePage() {
|
|||
<Box grow="Yes" style={{ maxWidth: toRem(300) }} direction="Column" gap="300">
|
||||
<Button
|
||||
as="a"
|
||||
href="https://github.com/cinnyapp/cinny"
|
||||
href="https://eureka.gamecult.org/forge/GameCult/Ratatoskr"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
before={<Icon size="200" src={Icons.Code} />}
|
||||
|
|
@ -42,18 +42,6 @@ export function WelcomePage() {
|
|||
Source Code
|
||||
</Text>
|
||||
</Button>
|
||||
<Button
|
||||
as="a"
|
||||
href="https://cinny.in/#sponsor"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
fill="Soft"
|
||||
before={<Icon size="200" src={Icons.Heart} />}
|
||||
>
|
||||
<Text as="span" size="B400" truncate>
|
||||
Support
|
||||
</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</PageHero>
|
||||
|
|
|
|||