Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/i18n-automerge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ jobs:
github.event.pull_request.base.ref == 'main' &&
github.event.pull_request.head.ref == 'l10n_main'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- uses: actions/checkout@v6
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/i18n-update-readme.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ jobs:
update-readme:
if: github.repository == 'cheeaun/phanpy'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/main2prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ jobs:
auto-pull-request:
if: github.repository == 'cheeaun/phanpy'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: vsoch/pull-request-action@master
env:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/rollbar-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ jobs:
group: rollbar-deploy
cancel-in-progress: true
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v6

Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/update-catalogs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ jobs:
update-catalogs:
if: github.repository == 'cheeaun/phanpy'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v6
with:
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,16 @@ Recap: Mastodon v4.3 features (https://github.com/mastodon/mastodon/releases/tag
- ↕️ Preliminary support for vertical-lr writing mode
- 🐛 Bug fixes

## May 15, 2026

📢 https://mastodon.social/@cheeaun/116578836866401369

- 🔄 Experimental paginated timeline
- 🪣 Multi-filters for profile posts
- 🧘 Wellbeing: hide trending, local or federated timelines
- 📱 Haptics
- 🐛 Bug fixes

<!--

## Next
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ Everything is designed and engineered following my taste and vision. This is a p

## Development

Prerequisites: Node.js 20+
Prerequisites: Node.js 22+

- `npm install` - Install dependencies
- `npm run dev` - Start development server and `messages:extract` (`clean` + `watch`) in parallel
Expand Down Expand Up @@ -396,6 +396,7 @@ Costs involved in running and developing this web app:
- <img src="https://crowdin-static.cf-downloads.crowdin.com/avatar/13454728/medium/1f78b7124b3c962bc4ae55e8d701fc91_default.png" alt="" width="16" height="16" /> isard (Catalan)
- <img src="https://crowdin-static.cf-downloads.crowdin.com/avatar/16646485/medium/5d76c44212a4048a815ab437fb170856_default.png" alt="" width="16" height="16" /> kaliuwu (Polish)
- <img src="https://crowdin-static.cf-downloads.crowdin.com/avatar/16532403/medium/4cefb19623bcc44d7cdb9e25aebf5250.jpeg" alt="" width="16" height="16" /> karlafej (Czech)
- <img src="https://crowdin-static.cf-downloads.crowdin.com/avatar/17707804/medium/8804293de4f1835fb9b1b18d656b3e54.png" alt="" width="16" height="16" /> Kweerk1223 (Portuguese, Brazilian)
- <img src="https://crowdin-static.cf-downloads.crowdin.com/avatar/14677260/medium/e9f17e62ab69ed6212a16c94d779e7f3.png" alt="" width="16" height="16" /> Kytta (German)
- <img src="https://crowdin-static.cf-downloads.crowdin.com/avatar/16529521/medium/ae6add93a901b0fefa2d9b1077920d73.png" alt="" width="16" height="16" /> llun (Thai)
- <img src="https://crowdin-static.cf-downloads.crowdin.com/avatar/16291756/medium/a662122faa4f9a71b259b0e561f923b4.png" alt="" width="16" height="16" /> lucsdev24 (Occitan, Portuguese, Portuguese, Brazilian)
Expand Down
12 changes: 12 additions & 0 deletions public/sw.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ navigationPreload.enable();

self.__WB_DISABLE_DEV_LOGS = true;

self.addEventListener('activate', (event) => {
event.waitUntil(self.clients.claim());
});

// Cache HTML pages
pageCache({
warmCache: ['./compose/'],
Expand Down Expand Up @@ -151,6 +155,14 @@ const iconsRoute = new Route(
new CacheFirst({
cacheName: 'icons',
plugins: [
// Only enable AssetHashPlugin in production
...(import.meta.env.PROD
? [
new AssetHashPlugin({
maxHashes: 2, // Keep only 2 most recent hashes of each icon
}),
]
: []),
new ExpirationPlugin({
// Weirdly high maxEntries number, due to some old icons suddenly disappearing and not rendering
// NOTE: Temporary fix
Expand Down
4 changes: 2 additions & 2 deletions src/components/columns.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ function Columns() {
useKey: true,
ignoreEventWhen: (e) => {
// Allow number even with Shift (e.g. French AZERTY requires Shift for numbers)
if (/^[1-9]$/.test(e.key)) return false;
return e.metaKey || e.ctrlKey || e.altKey || e.shiftKey;
const isDigit = /^[1-9]$/.test(e.key);
return e.metaKey || e.ctrlKey || e.altKey || (e.shiftKey && !isDigit);
},
},
);
Expand Down
19 changes: 10 additions & 9 deletions src/components/qr-code.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,16 @@ export default function QrCode({

if (!text) return null;

const qrData = useMemo(
() =>
encodeQR(text, 'raw', {
ecc: 'high',
border: 0,
scale: 1,
}),
[text],
);
const qrData = useMemo(() => {
const raw = encodeQR(text, 'raw', {
ecc: 'high',
border: 1,
scale: 1,
});
// Strip the 1-cell border added by the QR library, since we
// handle padding ourselves in the SVG rendering
return raw.slice(1, -1).map((row) => row.slice(1, -1));
}, [text]);
const gridSize = qrData.length;

const centerExcludeSize = arenaLoaded ? Math.ceil(gridSize * 0.3) : 0;
Expand Down
4 changes: 2 additions & 2 deletions src/components/shortcuts.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ function Shortcuts() {
useKey: true,
ignoreEventWhen: (e) => {
// Allow number even with Shift (e.g. French AZERTY requires Shift for numbers)
if (/^[1-9]$/.test(e.key)) return false;
return e.metaKey || e.ctrlKey || e.altKey || e.shiftKey;
const isDigit = /^[1-9]$/.test(e.key);
return e.metaKey || e.ctrlKey || e.altKey || (e.shiftKey && !isDigit);
},
},
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/status.css
Original file line number Diff line number Diff line change
Expand Up @@ -2283,7 +2283,7 @@ a.card:is(:hover, :focus):visited {

.poll-options.truncated & {
content-visibility: auto;
content-intrinsic-size: auto 1.5lh;
content-intrinsic-size: auto 2rem;
}

&:has(> label) {
Expand Down
9 changes: 6 additions & 3 deletions src/components/timeline.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ function Timeline({
}) {
const { t } = useLingui();
const snapStates = useSnapshot(states);
const autoHideBars = snapStates.settings.autoHideBars;
const [items, setItems] = useState([]);
const [uiState, setUIState] = useState('start');
const [showMore, setShowMore] = useState(false);
Expand Down Expand Up @@ -302,7 +303,8 @@ function Timeline({
if (!value.length) done = true;
setShowMore(!done);
} else {
setShowMore(false);
// Iterator error state returns undefined - treat as error, not end of list
throw new Error('Timeline load failed');
}
setUIState('default');
__BENCHMARK.end(`timeline-${id}-load`);
Expand Down Expand Up @@ -363,15 +365,16 @@ function Timeline({
const scrollFnCallback = useCallback(
({ scrollDirection, nearReachStart, reachStart }) => {
if (headerRef.current) {
const hiddenUI = scrollDirection === 'end' && !nearReachStart;
const hiddenUI =
autoHideBars && scrollDirection === 'end' && !nearReachStart;
headerRef.current.hidden = hiddenUI;
}
setNearReachStart(nearReachStart);
if (reachStart) {
loadItems(true);
}
},
[setNearReachStart, loadItems],
[setNearReachStart, loadItems, autoHideBars],
);
const { resetScrollDirection } = useScrollFn(
{
Expand Down
14 changes: 12 additions & 2 deletions src/components/timeline2.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
useState,
} from 'preact/hooks';
import { useDebouncedCallback, useThrottledCallback } from 'use-debounce';
import { useSnapshot } from 'valtio';

import { api } from '../utils/api';
import FilterContext from '../utils/filter-context';
Expand Down Expand Up @@ -97,6 +98,8 @@ function Timeline2({
// clearWhenRefresh,
}) {
const { t } = useLingui();
const snapStates = useSnapshot(states);
const autoHideBars = snapStates.settings.autoHideBars;
const { masto } = api({ instance });

const cacheKey = `timeline2-${id}`;
Expand Down Expand Up @@ -279,6 +282,12 @@ function Timeline2({

const { max_id, min_id } = params;
let { value, originalValue, done } = result;

// Iterator error state returns undefined - treat as error, not end of list
if (value === undefined || value === null) {
throw new Error('Timeline load failed');
}

const hasOlder = !done;
const minIDValue = originalValue[0]?.id;
const maxIDValue = originalValue[originalValue.length - 1]?.id;
Expand Down Expand Up @@ -396,12 +405,13 @@ function Timeline2({
scrollDirection,
nearReachStart,
});
headerRef.current.hidden = scrollDirection === 'end' && !nearReachStart;
headerRef.current.hidden =
autoHideBars && scrollDirection === 'end' && !nearReachStart;
}
// Cache scroll position on scroll
cacheScrollAnchor();
},
[cacheScrollAnchor],
[cacheScrollAnchor, autoHideBars],
);
const { resetScrollDirection } = useScrollFn(
{
Expand Down
Loading
Loading