cq

Distributed social media platform
git clone git://git.finwo.net/app/cq
Log | Files | Refs

commit 6a3fe4cef03e8dda602d96b4eaeb1c38ce385007
parent 0b27b71699c814b237a9e56d54a75d43283d44ff
Author: finwo <finwo@pm.me>
Date:   Sat, 13 Sep 2025 21:57:50 +0200

Added contacts page

Diffstat:
Mpackages/app/src/component/screen-account-select.tsx | 2+-
Apackages/app/src/component/screen-contact-add.tsx | 23+++++++++++++++++++++++
Apackages/app/src/component/screen-contact-list.tsx | 42++++++++++++++++++++++++++++++++++++++++++
Mpackages/app/src/component/screen-home.tsx | 16++++++++--------
Apackages/app/src/component/screen-menu.tsx | 42++++++++++++++++++++++++++++++++++++++++++
Dpackages/app/src/component/screen-settings.tsx | 38--------------------------------------
Mpackages/app/src/global.css | 20++++++++++++++------
Mpackages/app/src/main.ts | 8++++++--
8 files changed, 136 insertions(+), 55 deletions(-)

diff --git a/packages/app/src/component/screen-account-select.tsx b/packages/app/src/component/screen-account-select.tsx @@ -59,7 +59,7 @@ export const AccountSelectScreen = { <div id="accountSelectList"> {vnode.state.accounts.map(account => ( <a style="display:block;padding:1em" onclick={vnode.state.handler.selectAccount(account)}> - {account.displayName} + <label>{account.displayName}</label> <svg ns="http://www.w3.org/2000/svg" fill="transparent" style="vertical-align:bottom;width:1em;height:1em;" class="accountListDeleteButton" onclick={()=>{vnode.state.handler.deleteAccount(vnode, account);return false;}}> {TrashIcon.map(el => m(...el))} </svg> diff --git a/packages/app/src/component/screen-contact-add.tsx b/packages/app/src/component/screen-contact-add.tsx @@ -0,0 +1,23 @@ +type _Vnode = Vnode<{}, typeof ContactAddScreen>; + +import BackIcon from 'lucide/dist/esm/icons/arrow-left.js'; +import {ContactListScreen} from './screen-contact-list'; + +export const ContactAddScreen = { + routePath: '/contacts/add', + + view(vnode: _Vnode) { + return ( + <div class="main"> + <h3>Add contact</h3> + <a href={`#!${ContactListScreen.routePath}`} style="position:absolute;right:0;top:-0.9em;background:none;border:none;"> + <svg ns="http://www.w3.org/2000/svg" fill="transparent" style="vertical-align:bottom;width:1em;height:1em;"> + {BackIcon.map(el => m(...el))} + </svg> + </a> + + TODO + </div> + ); + }, +}; diff --git a/packages/app/src/component/screen-contact-list.tsx b/packages/app/src/component/screen-contact-list.tsx @@ -0,0 +1,42 @@ +type _Vnode = Vnode<{}, typeof ContactListScreen>; + +import BackIcon from 'lucide/dist/esm/icons/arrow-left.js'; + +import {AccountSelectScreen} from './screen-account-select'; +import {MenuScreen} from './screen-menu'; +import {ContactAddScreen} from './screen-contact-add'; + +export const ContactListScreen = { + routePath: '/contacts', + + handler: { + accountSwitch() { + localStorage.removeItem('selectedAccount'); + document.location.href=`#!${AccountSelectScreen.routePath}`; + } + }, + + async oninit(vnode: _Vnode) { + }, + + view(vnode: _Vnode) { + return ( + <div class="main"> + <h3>Contacts</h3> + <a href={`#!${MenuScreen.routePath}`} style="position:absolute;right:0;top:-0.9em;background:none;border:none;"> + <svg ns="http://www.w3.org/2000/svg" fill="transparent" style="vertical-align:bottom;width:1em;height:1em;"> + {BackIcon.map(el => m(...el))} + </svg> + </a> + + <div class="entry-list"> + <a style="display:block;cursor:pointer;" href={`#!${ContactAddScreen.routePath}`}> + <label> + Add contact + </label> + </a> + </div> + </div> + ); + }, +}; diff --git a/packages/app/src/component/screen-home.tsx b/packages/app/src/component/screen-home.tsx @@ -1,8 +1,8 @@ import {getFileHandle} from "../util/opfs"; import { AccountSelectScreen } from "./screen-account-select"; -import SettingsIcon from 'lucide/dist/esm/icons/settings.js'; -import {SettingsScreen} from "./screen-settings"; +import MenuIcon from 'lucide/dist/esm/icons/menu.js'; +import {MenuScreen} from "./screen-menu"; type _Vnode = Vnode<{}, typeof HomeScreen>; @@ -47,11 +47,11 @@ export const HomeScreen = { return ( <div class="main"> <h3>Chats</h3> - <button onclick={() => document.location.href=`#!${SettingsScreen.routePath}`} style="position:absolute;right:0;top:-1.2em;background:none;border:none;"> + <a href={`#!${MenuScreen.routePath}`} style="position:absolute;right:0;top:-0.9em;background:none;border:none;"> <svg ns="http://www.w3.org/2000/svg" fill="transparent" style="vertical-align:bottom;width:1em;height:1em;"> - {SettingsIcon.map(el => m(...el))} + {MenuIcon.map(el => m(...el))} </svg> - </button> + </a> <div class="entry-list"> {vnode.state.contacts.map((contact: Contact) => ( @@ -61,15 +61,15 @@ export const HomeScreen = { </div> ))} <div> - <b>Nikola Tesla</b><br/> + <label>Nikola Tesla</label><br/> <small>Some old message here</small> </div> <div> - <b>Charlie</b><br/> + <label>Charlie</label><br/> <small>Some old message here</small> </div> <div> - <b>Alice</b><br/> + <label>Alice</label><br/> <small>Some old message here</small> </div> </div> diff --git a/packages/app/src/component/screen-menu.tsx b/packages/app/src/component/screen-menu.tsx @@ -0,0 +1,42 @@ +type _Vnode = Vnode<{}, typeof MenuScreen>; + +import BackIcon from 'lucide/dist/esm/icons/arrow-left.js'; +import {HomeScreen} from './screen-home'; +import {AccountSelectScreen} from './screen-account-select'; +import {ContactListScreen} from './screen-contact-list'; + +export const MenuScreen = { + routePath: '/menu', + + handler: { + accountSwitch() { + localStorage.removeItem('selectedAccount'); + document.location.href=`#!${AccountSelectScreen.routePath}`; + } + }, + + async oninit(vnode: _Vnode) { + }, + + view(vnode: _Vnode) { + return ( + <div class="main"> + <h3>Menu</h3> + <a href={`#!${HomeScreen.routePath}`} style="position:absolute;right:0;top:-0.9em;background:none;border:none;"> + <svg ns="http://www.w3.org/2000/svg" fill="transparent" style="vertical-align:bottom;width:1em;height:1em;"> + {BackIcon.map(el => m(...el))} + </svg> + </a> + + <div class="entry-list"> + <a style="display:block;cursor:pointer;" href={`#!${ContactListScreen.routePath}`}> + <label>Contacts</label> + </a> + <a style="display:block;cursor:pointer;" onclick={vnode.state.handler.accountSwitch}> + <label>Switch account</label> + </a> + </div> + </div> + ); + }, +}; diff --git a/packages/app/src/component/screen-settings.tsx b/packages/app/src/component/screen-settings.tsx @@ -1,38 +0,0 @@ -type _Vnode = Vnode<{}, typeof SettingsScreen>; - -import BackIcon from 'lucide/dist/esm/icons/arrow-left.js'; -import {HomeScreen} from './screen-home'; -import {AccountSelectScreen} from './screen-account-select'; - -export const SettingsScreen = { - routePath: '/settings', - - handler: { - accountSwitch() { - localStorage.removeItem('selectedAccount'); - document.location.href=`#!${AccountSelectScreen.routePath}`; - } - }, - - async oninit(vnode: _Vnode) { - }, - - view(vnode: _Vnode) { - return ( - <div class="main"> - <h3>Settings</h3> - <button onclick={() => document.location.href=`#!${HomeScreen.routePath}`} style="position:absolute;right:0;top:-1.2em;background:none;border:none;"> - <svg ns="http://www.w3.org/2000/svg" fill="transparent" style="vertical-align:bottom;width:1em;height:1em;"> - {BackIcon.map(el => m(...el))} - </svg> - </button> - - <div class="entry-list"> - <a style="display:block;cursor:pointer;" onclick={vnode.state.handler.accountSwitch}> - <b>Switch account</b> - </a> - </div> - </div> - ); - }, -}; diff --git a/packages/app/src/global.css b/packages/app/src/global.css @@ -26,12 +26,15 @@ h1, h2, h3, h4, h5, h6, legend, label { font-weight: 500; } +small { + font-size: 0.8em; +} + a[href] { color: inherit; text-decoration: underline; } - input:focus, select:focus, textarea:focus, @@ -65,11 +68,16 @@ svg { } } -.entry-list > * { - padding: 1em; - border-top: 1px solid #FFF8; - &:hover { - background: #FFF2; +.entry-list { + > a[href] { + text-decoration: none; + } + > * { + padding: 1em; + border-top: 1px solid #FFF8; + &:hover { + background: #FFF2; + } } } diff --git a/packages/app/src/main.ts b/packages/app/src/main.ts @@ -2,12 +2,16 @@ globalThis.m = require('mithril'); import { AccountCreateScreen } from './component/screen-account-create.tsx'; import { AccountSelectScreen } from './component/screen-account-select.tsx'; +import {ContactAddScreen} from './component/screen-contact-add.js'; +import {ContactListScreen} from './component/screen-contact-list.js'; import { HomeScreen } from './component/screen-home.js'; -import {SettingsScreen} from './component/screen-settings.js'; +import {MenuScreen} from './component/screen-menu.js'; m.route(document.body, "/", { [HomeScreen.routePath ]: HomeScreen, [AccountSelectScreen.routePath]: AccountSelectScreen, [AccountCreateScreen.routePath]: AccountCreateScreen, - [SettingsScreen.routePath ]: SettingsScreen, + [MenuScreen.routePath ]: MenuScreen, + [ContactListScreen.routePath ]: ContactListScreen, + [ContactAddScreen.routePath ]: ContactAddScreen, });