Skip to content

Latest commit

 

History

History
42 lines (35 loc) · 12.5 KB

migration-list-apps.md

File metadata and controls

42 lines (35 loc) · 12.5 KB

Migration — Posts, Pages, Users, User Edit, Plugins and Comments become App Framework apps

The six native list windows are now .os.php apps under apps/ — apps/posts/, apps/pages/, apps/users/, apps/user-edit/, apps/plugins/, apps/comments/ — driven by the App Framework instead of three PHP modules plus three TypeScript bundles. Every window keeps its frozen id (desktop-mode-posts, desktop-mode-pages, desktop-mode-users, desktop-mode-user-edit, desktop-mode-plugins, desktop-mode-comments), its title, size, gate, opt-in setting and URL remap, so dock tiles, session restore, desktop shortcuts and the nativeXEnabled toggles carry over untouched. Same windows, same rows, same styling on a desk and on a phone; new plumbing.

Removed

Surface Replacement
Filters openstation_posts_window_args, openstation_pages_window_args, openstation_users_window_args, openstation_user_edit_window_args, openstation_plugins_window_args, openstation_comments_window_args openstation_app_manifest — $manifest['width'], ['icon'], ['title'], ['config'] (the former config blob, now the config extra), … for the matching $id; openstation_app_window_args for the registration args.
Filters openstation_*_window_template_html (all six) There is no server template. Each body is a client view; the data-os-posts-*, data-os-users-*, data-os-plugins-* and data-os-comments-* hooks still mark the same elements, and the old root classes (desktop-mode-posts, desktop-mode-users, desktop-mode-plugins, os-comments) are still on the roots for third-party CSS.
PHP openstation_*_window_render_template() / _register_window() / _default_query_args() callers of openstation_register_window() The apps register themselves through the framework. openstation_*_window_default_query_args() still exist (the openstation_*_window_query_args filters are unchanged) and now feed each app's data().
Script handles os-posts-window, os-plugins-window, os-comments-window; bundles assets/js/{posts,plugins,comments}-window[.min].js; style handles of the same names; assets/css/{posts,plugins,comments}-window.css The shared openstation-app-runtime bundle plus each app's companion client view (assets/js/apps/<name>[.min].js) and stylesheet (apps/<dir>/<name>.css, registered on first open). The list layout Posts, Pages and Users share (.os-app-list__*) is in assets/css/app-runtime.css; apps/user-edit/ points at apps/users/users.css.
wp.os.getWindowConfig( id ) keys postsUrl, usersUrl, commentsUrl, bulkUrl, replyUrl, createUserUrl, insightsUrlBase, pluginsUrl, queryArgs, … The list is the app's data(); the static facts an app still needs ride wp.os.getWindowConfig( id ).extra (ctx.extra in the client view): mode, editPostUrlBase, newPostUrl, defaultOrderby / defaultOrder (what a cleared column sort returns to), frontPageId / postsPageId / pageTemplates (Pages), the capability flags and role / locale / colour-scheme / contact-method maps from one memoised openstation_users_profile_facts() (Users and User Edit share it), caps, ajaxUrl, ajaxNonce, updatesNonce, autoUpdatesEnabled, selfPluginFile, adminUrl (Plugins), canModerate, canEditComments (Comments).
The shared stores desktop-mode/user-edit/target (setUserEditTarget() / readUserEditTarget() / subscribeUserEditTarget() in src/posts-window/user-edit-target.ts), desktop-mode/comments/post-filter (setCommentsPostFilter()), desktop-mode/plugins-window/tab-target (setPluginsWindowTab()) Open-time params. wp.os.openWindow( 'desktop-mode-user-edit', { params: { userId } } ) — or openUserEditWindow( userId, { source, fallback } ) from src/open-targets/user-edit-window.ts, the door WP Explorer and the agents roster use; wp.os.openWindow( 'desktop-mode-comments', { params: { post } } ) (0 clears the scope); wp.os.openWindow( 'desktop-mode-plugins', { params: { tab: 'installed' | 'browse' | 'featured' } } ). The URL remaps pass the same params. Each app reads them on mount; a live singleton retargets through the new reopen lifecycle action; params ride the session, so a reload restores the same person, scope or tab.
The whole src/posts-window/, src/plugins-window/, src/comments-window/ directories and includes/{posts,pages,users,user-edit,plugins,comments}-window/ The apps own their code: apps/<dir>/<name>.os.php + parts/*.php (permissions, REST fields and routes, AJAX handlers — the same global function names), apps/<dir>/<name>.os.ts + parts/*.ts (cell renderers, columns, the canvases, the profile component, the plugin views, the conversation view). The <os-user-profile> element lives in apps/users/parts/ and is shared by the Users and User Edit bundles.
openstation_comments_window_after_bulk firing only from the REST route It also fires from the Comments app's moderate action, since both run openstation_comments_window_moderate().
The Users default _fields carrying openstation_assignable_roles, url, description; the openstation_user_stats field feeding the table The app computes the page's content counts in two grouped queries (openstation_users_window_stats_for()) and reads the assignable roles off its config extra. Every REST field stays registered; openstation_users_window_query_args adds them back for a consumer that reads them off the rows.
<os-user-profile> compiled into the Users and User Edit bundles, resolving its config from window.openStationWindowConfig One companion bundle, assets/js/apps/user-profile[.min].js (script handle openstation-user-profile, registered by apps/users/parts/profile-script.php and appended to both windows through openstation_app_window_args). The element takes config / fetch / toast properties from the app that mounts it and falls back to the shell when unfed; the Users app mounts it only when the Profile tab is picked.
Filter openstation_comments_window_reply_editor Gone. The composer is a plain <os-textarea>; the filter never selected anything else ('rich' and 'gutenberg' were never implemented).
The Comments default _fields carrying openstation_replies_count and openstation_can_moderate The app computes the page's reply counts in one grouped query and ships the moderation cap in its config extra. Both REST fields stay registered; openstation_comments_window_query_args adds them back for a consumer that reads them off the rows.
os.plugin.changed broadcasts with source: 'plugins-window' source: 'plugins-app', carrying the changed plugins' ids. os.post.changed keeps source: 'posts-window'; a Pages trash now announces page, not post.
The ?openstation_force_refresh=1 flag on the Plugins window's Refresh (openstation_plugins_window_force_refresh_requested()) Gone. Refresh is the app's reload action, which forces the update check through openstation_plugins_window_prime_updates_once( true ); the openstation_plugins_window_refresh_updates filter still receives $force.
One dm_pwsz_<md5> size transient per plugin One dm_pwsz_map transient for the whole install, read once per request and invalidated on upgrader_process_complete / deleted_plugin.
The Browse request's updated sort and tag filter; banners, contributors, donate_link in the wp.org calls Removed — nothing in the window offered them. openstation_plugins_window_browse_args no longer sees a tag in its raw params.
The dock drop-target id os-plugins-window/dock desktop-mode-plugins/dock.
A plugin delete dispatch reaching Core's controller on a network Refused, like the admin-ajax half already was. openstation_plugins_window_caps() is the screen gate — Core's site plugins screen offers no Delete, the files are the network admin's — and a super admin holds delete_plugins, so the action enforces the gate rather than the bare capability.

Unchanged

  • The open. A window paints its frame the moment it opens — the client view's placeholder (app-framework.md), with the table's skeleton or the rail's ghost rows until mount lands the page — and the shell prefetches every app bundle and sheet in idle time after boot, so a first open waits on neither the download nor the shell's overlay. With "Prewarm windows on hover" on, a hover over the tile sends the window's first mount ahead of the click (wp.os.prewarmWindow()), and the rows are there when it opens.
  • The gates: openstation_{posts,pages,users,plugins,comments}_window_user_can_register / _user_can_use, openstation_user_edit_window_user_can_register, openstation_users_window_assignable_roles.
  • The query-args filters: openstation_{posts,pages,users,comments}_window_query_args, openstation_pages_window_template_labels — the same _fields / _embed / post_type reach the same Core REST controllers, in-process, so every register_rest_field(), the rest_post_query tags-AND filter and the openstation_* fields land on the rows exactly as before.
  • Every REST route under /desktop-mode/v1: /term-counts, /tag-cooccurrence, /users*, /users/{id}/*, /comments/* — see includes/rest/README.md for the new handler files. The app actions share one PHP function per operation with them.
  • Every other openstation_plugins_window_* filter and action (_browse_args, _browse_response, _info_response, _review_parser, _icon_url, _local_icon_candidates, _refresh_updates, _auto_updates_enabled, _installed, the featured-slugs pair), the wp_ajax_openstation_plugins_* handlers, openstation_plugins_window_count_visible_updates() (the dock badge).
  • openstation_comments_window_spam_score, openstation_users_window_user_created, _login_recorded, openstation_user_edit_window_insights, OPENSTATION_LAST_LOGIN_META_KEY. (openstation_comments_ai_is_enabled, _toggled and the AI moderation option were unchanged by this migration but have since been removed — see migration-comments-ai-scoring.md.)
  • The JS extension points of the Posts window: the openstation.postsWindow.columns / statusSegments / bulkActions / toolbarTrailing filters, the openstation.postsWindow.opened / dataLoaded actions, the os-posts-window-opened / os-posts-window-data-loaded CustomEvents, the PostsWindowContext / BulkAction / StatusSegment shapes (now exported from apps/posts/parts/types.ts), the os.post.changed and os.term.changed broadcasts, the nativePostsHiddenColumns setting behind "Show columns".
  • The wporg-plugin drag payload and the dock drop target, the plugins update queue and icon fallback chain, the upload dialog, the self-deactivate reload.
  • The phone layouts: the status picker, the card list, the bottom bulk bar, the folded Categories / Tags editors, the one-pane Comments view.

Why

The six windows were 35,359 lines — 24,489 of TypeScript across three bundles, 7,517 of PHP registration / template / REST glue, 3,353 of CSS (the deleted files at trunk, counted with wc -l) — and each carried its own copy of the same plumbing: a config blob, a REST client for the list, pager DOM, toolbar wiring, a shared store to smuggle a deep link past openById(). As apps they are 25,737 lines: 24,816 under the six apps/<dir>/ directories (every file except *.test.ts; PHP, TypeScript and CSS alike) plus the 921 net lines the framework grew (git diff --numstat against trunk over includes/framework/, src/app-runtime/, app-runtime.css and the shell seams) to absorb that plumbing for every future list too: openstation_app_rest() / openstation_app_rest_page() (in-process Core REST with _fields and _embed, so a data() serves the exact rows a browser fetched), the reopen lifecycle and per-session params (the deep-link contract), App::config( callable ) (per-viewer config resolved when the manifest is built), the own-echo skip on watch() (a window's announce never costs it a second round trip), the list-window furniture (statusControl(), pager(), mountMenuCheckboxes(), createListTableSync()) and the shared .os-app-list__* layout with its phone rules. The test surface grew from 2,247 lines (the deleted vitest and registration suites) to 5,998 (app vitest 2,829, app PHPUnit 2,444, framework 725).