wayBetter for X

This commit is contained in:
CRTkafa 2026-10-01 06:01:13 +07:00
commit 434f193217
720 changed files with 147465 additions and 0 deletions

View file

@ -0,0 +1,124 @@
// wayBetter for X on the wayBetter panel (waybetter/packages/shell/src/panel, createPanel): the
// panel itself (navigation, settings search, Appearance and the Theme Builder, plugins, the Store,
// Make, accounts, Power User, settings, backup and sync, developer mode, updates) is the
// framework's; this module tells it about X: the home page's words, X's themes and their miniature
// (ThemePreview), X's own section (Drafts), Make's examples and docs, the languages, and what X's
// native side serves. The Plugins section shows X's feature table (src/areas/table.ts): eight area
// plugin cards, then the fixes; the logo and wording are in Appearance, and the modes (Basic,
// Advanced, Power User) in Settings and on the first-run screen.
import { X_ICON_PACKS } from '../inject/themeStructure';
import { getVersion } from '@tauri-apps/api/app';
import PLUGINS_MD from '../../../../docs/PLUGINS.md?raw';
import THEMES_MD from '../../../../docs/THEMES.md?raw';
import IDEAS_MD from '../../../../docs/PLUGIN-IDEAS.md?raw';
// X's own sections first: the panel's styles load after theirs, as they always did.
import { Drafts } from './Drafts';
import { Branding, LayoutSettings } from './Branding';
import { ThemePreview } from './ThemePreview';
import { createPanel, type PanelSite } from '../../../../waybetter/packages/shell/src/panel/index.ts';
import { X_ELSEWHERE, X_TABLE } from '../areas/table';
import { language } from '../i18n/language.ts';
import { LANGUAGES, t } from '../i18n/index.ts';
import { ACCENTS, X_THEMES, resolvedTheme } from '../inject/theme';
import { installController } from '../shell/installStore';
import { themes } from '../shell/themes';
import { MEASURED_MB_PER_COLUMN, MEASURED_MB_RANGE } from '../shell/xColumns';
import { LOGO_PNG } from './logo-data';
import { PLUGIN_EXAMPLES, THEME_EXAMPLE } from './makeExamples';
import { createStringPacksSection } from '../../../../waybetter/packages/shell/src/panel/StringPacks.tsx';
import { X_WEB_PAGE_INVENTORY } from '../shell/stringPacks';
type XMode = 'light' | 'dim' | 'dark';
export const TRANSLATE_URL = 'https://git.crt.fyi/CRT/better-twttr/src/branch/main/docs/TRANSLATING.md';
const SITE_URL = 'https://waybetter.fyi/x/';
export const X_PANEL: PanelSite = {
brand: { name: 'wayBetter', logo: LOGO_PNG },
version: getVersion,
home: {
kicker: { name: 'wayBetter', rest: ' for X' },
title: () => [t('panel.home.titleBefore'), t('panel.home.titleEmphasis'), t('panel.home.titleAfter')],
lede: () => t('panel.home.lede'),
chips: () => [t('panel.home.foss'), 'GPL-3.0'],
actions: [
{ section: 'themes', label: () => t('panel.home.pickTheme') },
{ section: 'plugins', label: () => t('panel.home.browsePlugins') },
],
highlights: [
{ section: 'themes', title: () => t('panel.home.themes'), text: () => t('panel.home.themesText') },
{ section: 'plugins', title: () => t('panel.home.plugins'), text: () => t('panel.home.pluginsText') },
{ section: 'accounts', title: () => t('wb.panel.section.accounts'), text: () => t('panel.home.accountsText') },
],
about: {
title: () => t('panel.home.about'),
text: () => t('panel.home.aboutText'),
layers: [
{ name: () => t('panel.home.layer.shell'), text: () => t('panel.home.layer.shellText') },
{ name: () => t('panel.home.layer.runtime'), text: () => t('panel.home.layer.runtimeText') },
{ name: () => t('panel.home.layer.adapter'), text: () => t('panel.home.layer.adapterText') },
],
foot: { text: () => t('panel.home.madeBy'), by: '@CRTkafa', link: { label: 'waybetter.fyi/x', url: SITE_URL } },
},
},
sections: [
{ id: 'drafts', label: () => t('panel.section.drafts'), icon: 'M3 13l.6-2.6L10.5 3.5l2 2-6.9 6.9zM9 5l2 2', component: Drafts },
createStringPacksSection({ inventory: X_WEB_PAGE_INVENTORY }),
],
order: ['home', 'themes', 'builder', 'plugins', 'store', 'languages', 'make', 'drafts', 'accounts', 'power', 'settings', 'backup', 'developer', 'updates'],
themes: {
store: themes,
catalog: X_THEMES,
accents: ACCENTS,
Preview: ThemePreview,
siteFont: "X's Chirp",
// X default keeps X's colors: a draft starts from X's own Lights out palette.
draftColors: { bg: '#000000', text: '#e7e9ea', accent: '#1d9bf0' },
// Theme engine v2: the built-in icon packs (the owner's pick travels in the theme choice).
iconPacks: X_ICON_PACKS.packs.map(pack => ({ id: pack.id, name: pack.name, description: pack.description })),
fileSuffix: '.bttheme.json',
chromePreview: { tabs: ['Home / X', '@waybetter', 'wayBetter'], chip: 'Twitter', page: 'Home' },
resolved: (choice, mode) => resolvedTheme(choice, mode as XMode),
modes: {
label: () => t('make.xDisplay'),
initial: 'dark',
options: [
{ value: 'light', label: () => t('make.xDefault') },
{ value: 'dim', label: () => t('make.xDim') },
{ value: 'dark', label: () => t('make.xLightsOut') },
],
},
},
cssExamples: {
custom: '/* Example: hide the right sidebar */\n[data-testid="sidebarColumn"] { display: none; }',
theme: '/* Example: a softer timeline divider */\n[data-testid="cellInnerDiv"] { border-bottom-color: transparent; }',
builder: '/* e.g. a softer divider */\n[data-testid="cellInnerDiv"] { border-bottom-color: transparent; }',
},
store: { controller: installController },
make: {
examples: PLUGIN_EXAMPLES,
themeExample: { file: 'midnight-mint.theme.json', source: THEME_EXAMPLE },
docs: { 'PLUGINS.md': PLUGINS_MD, 'THEMES.md': THEMES_MD, 'PLUGIN-IDEAS.md': IDEAS_MD },
},
languages: { list: LANGUAGES, state: language.state, subscribe: language.subscribe, set: language.set, translateUrl: TRANSLATE_URL },
appearance: { extra: [Branding] },
features: {
table: X_TABLE,
elsewhere: X_ELSEWHERE,
// Power User's tools beyond flags are the shell's: decks and workspaces, in their section.
onMode: mode => { if (mode === 'power') window.dispatchEvent(new CustomEvent('bt-panel-section', { detail: 'power' })); },
},
settings: { alerts: true, linkKeywords: 'x twitter', extra: [LayoutSettings] },
power: {
defaultFlags: ['disableVideoAutoplay', 'hidePromotedPosts', 'hideEngagementCounts', 'hideViewCounts'],
memory: { perColumn: MEASURED_MB_PER_COLUMN, range: MEASURED_MB_RANGE },
keysHint: () => t('power.keysHint'),
},
backup: true,
// "Share my setup" under Backup & sync: a setup carries this id and applies only to wayBetter for X.
setup: { app: 'x' },
updates: true,
};
/** The wayBetter tab of wayBetter for X. */
export const Panel = createPanel(X_PANEL);