147 lines
6.5 KiB
Markdown
147 lines
6.5 KiB
Markdown
# Dev Notes
|
|
|
|
This file documents some advices working on the app.
|
|
|
|
## Debugging for iOS
|
|
|
|
You can debug on the Safari on iOS only if you have mac (and run macOS). The certain workarounds don't work well. Here are some tips:
|
|
|
|
- [GNOME Web (epiphany)](https://apps.gnome.org/Epiphany/) uses webkit2gtk, the same engine from Safari. Most of bugs can be reproduced on it.
|
|
- For visual bugs: on you iDevice, redirect the localhost.direct to your dev computer. Now you have the hot reload on you iDevice.
|
|
- You can use network debugging apps like "Shadowrocket" to do such thing.
|
|
|
|
## The components don't react to the change as I setting the store, until the page reloaded
|
|
|
|
The `WritableAtom<unknwon>.set` might do an equals check. You must set a different object to ensure the atom sending a notify.
|
|
|
|
The code below may not notify the change:
|
|
|
|
```ts
|
|
export function updateAcctInf(idx: number) {
|
|
const o = $accounts.get();
|
|
// ...
|
|
o[idx].inf = inf;
|
|
$accounts.set(o);
|
|
}
|
|
```
|
|
|
|
Instead, set a new object:
|
|
|
|
```ts
|
|
export function updateAcctInf(idx: number) {
|
|
const o = $accounts.get();
|
|
// ...
|
|
o[idx] = Object.assign({}, o[idx], { inf });
|
|
$accounts.set(Array.from(o));
|
|
}
|
|
```
|
|
|
|
Ja, the code is weird, but that's the best we know. Anyway, you need new object on the path of your changed value.
|
|
|
|
## `transition: *-block or *-inline` does not work on WebKit
|
|
|
|
Idk why, but transition on logical directions may not work on WebKit - sometimes they work.
|
|
|
|
Use physical directions to avoid trouble, like "margin-top, margin-bottom".
|
|
|
|
## Safe area insets
|
|
|
|
For isolating control of the UI effect, we already setup css variables `--safe-area-inset-*`. In components, you should use the variables unless you have reasons to use `env()`.
|
|
|
|
Using `--safe-area-inset-*`, you can control the global value in settings (under dev mode).
|
|
|
|
## Module Isolation
|
|
|
|
> Write the code that can be easily removed.
|
|
|
|
To limit the code impact, we organize the code based on **"topic modules"** (modules in short). Each module focus on a specific topic described by the name. Like the "accounts" contains the code about the accounts, "masto" contains the code about the masto (a library used to access mastodon) helpers.
|
|
|
|
> Sidenote: This also helps easing "the landing problem". If you need something about accounts, no longer "common/accounts" and "hooks/accounts" and "helpers/accounts" and "components/accounts". Someone says this is clean - is it even if you need to jump between 6 directories for how one simple feature works?
|
|
> And you no longer needs to think about "where to place this file (between six directories, usually)". People often optimize their code structure too early - just like how they treat the runtime performance.
|
|
> The worse is, it's very hard to solve this problem later, because you had sent your code to different places.
|
|
|
|
There are **two special modules** in this project:
|
|
|
|
One is the *platform*. This module provides foundation of this app: deals with the host platform (like SizedTextarea - auto resized textarea), provides custom platform feature (like StackedRouter - provides mobile-native navigation experience).
|
|
|
|
The another is the *material*. This module provides Material styling toolkit, the stylesheets, MUI Theme, constants and components.
|
|
|
|
They (and only them) can be accessed by special aliases: `~{module name}`, like the `~platform`.
|
|
|
|
We discourage cross referencings between two topics. Reuse is not better than duplication. Cross referencing is still possible if required.
|
|
|
|
When a tool, a file or a component is required every-elsewhere, **promoting** is required to reduce the cross referencing. Thanksfully, it's usually automated process for moving files.
|
|
|
|
But, sometimes you need a redesigned (sometimes better) tool for the generic usage. Follow the idea:
|
|
|
|
- Move slowly or crash. Only make the change if it's required.
|
|
- Try to make the original part depends on your new tool, and keep the original for awhile.
|
|
- Mark deprecated only if you think the original won't worth an existence. Reasons:
|
|
- Migrate to the new code only needs minor change.
|
|
- The original code has critical problems, like performance or compatibility.
|
|
- Make notes. Communication is important, even with the future you.
|
|
- *Why* this move is decided?
|
|
- *What* this new tool does?
|
|
- *How* this tool works?
|
|
- Clean up code regularly. Don't keep the unused code forever.
|
|
|
|
## Managing CSS
|
|
|
|
Two techniques are still:
|
|
|
|
- Styled compoenent (solid-styled)
|
|
- Native CSS with CSS layering
|
|
|
|
The second is recommended for massive use. A stylesheet for a component can be placed alongside
|
|
the component's file. The stylesheet must use the same name as the component's file name, but replace the extension with
|
|
`.css`. Say there is a component file "PreviewCard.tsx", the corresponding stylesheet is "PreviewCard.css". They are imported
|
|
by the component file, so the side effect will be applied by the bundler.
|
|
|
|
The speicifc component uses a root class to scope the rulesets' scope. This convention allows the component's style can be influenced
|
|
by the other stylesheets. It works because Tutu is an end-user application, we gain the control of all stylesheets in the app (kind of).
|
|
Keep in mind that the native stylesheets will be applied globally at any time, you must carefully craft the stylesheet to avoid leaking
|
|
of style.
|
|
|
|
Three additional CSS layers are declared as:
|
|
|
|
- compat: Compatibility rules, like normalize.css
|
|
- theme: The theme rules
|
|
- material: The internal material styles
|
|
|
|
When working on the material package, if the style is intended to work with the user styles,
|
|
it must be declared under the material layer. Otherwise the unlayer, which has the
|
|
highest priority in the author's, can be used.
|
|
|
|
Styled component is still existing. Though styled component, using attributes for scoping,
|
|
may not be as performant as the techniques with CSS class names;
|
|
it's still provided in the code infrastructure for its ease.
|
|
|
|
The following is an example of the recommended usage of solid-styled:
|
|
|
|
```tsx
|
|
// An example of using solid-styled
|
|
import { css } from "solid-styled";
|
|
import { createSignal } from "solid-js";
|
|
|
|
const Component = () => {
|
|
const [width, setWidth] = createSignal(100);
|
|
|
|
css`
|
|
.root {
|
|
width: ${width()}%;
|
|
}
|
|
`
|
|
return <div class="root"></div>
|
|
};
|
|
```
|
|
|
|
When developing new component, you can use styled component at first, and migrate
|
|
to native css slowly.
|
|
|
|
Before v2.0.0, there are CSS modules in use, but they are removed:
|
|
|
|
- Duplicated loads
|
|
- Unaware of order (failed composing)
|
|
- Not-ready for hot reload
|
|
|
|
In short, CSS module does not works well if the stylesheet will be accessed from more than one component.
|