PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.8
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.8
1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 0.8.8 0.8.7 0.8.6 All 33 releases
desktop-mode / includes / framework / app / class-effects.php

class-effects.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 1.1.8, at includes/framework/app/class-effects.php

224 lines 6.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * OpenStation App Framework — effects.
4 *
5 * What an action wants the shell to do besides repainting the body:
6 * show a toast, retitle the window, close it, open another one, set
7 * a badge, pop a context menu. An action calls `$os->toast( … )`; the
8 * runtime ships the list to the client, which performs each one
9 * after the morph.
10 *
11 * @package OpenStation
12 */
13
14 namespace OpenStation\App;
15
16 // Direct access, unless a standalone host is booting on bare PHP.
17 if ( ! defined( 'ABSPATH' ) ) {
18 defined( 'OPENSTATION_STANDALONE' ) || exit;
19 }
20
21 /**
22 * Queue of shell effects for one dispatch.
23 */
24 final class Effects {
25
26 /**
27 * @var array<int,array<string,mixed>>
28 */
29 private $items = array();
30
31 /**
32 * Show a toast.
33 *
34 * There is no tone: the shell renders every toast the same way
35 * (`wp.os.showToast()` takes no severity), so a `$tone` argument
36 * here would be a promise the platform cannot keep. Say what
37 * happened in the message, and use `<os-notice tone="…">` in the
38 * body when a state needs a colour.
39 *
40 * @param string $message Text.
41 * @return self
42 */
43 public function toast( $message ) {
44 return $this->add( 'toast', array( 'message' => (string) $message ) );
45 }
46
47 /**
48 * Retitle the window for this session.
49 *
50 * @param string $title New title.
51 * @return self
52 */
53 public function title( $title ) {
54 return $this->add( 'title', array( 'title' => (string) $title ) );
55 }
56
57 /**
58 * Close the window once the response lands.
59 *
60 * @return self
61 */
62 public function close() {
63 return $this->add( 'close', array() );
64 }
65
66 /**
67 * Open (or focus) another registered window.
68 *
69 * @param string $window_id Native window id.
70 * @return self
71 */
72 public function open( $window_id ) {
73 return $this->add( 'open', array( 'window' => (string) $window_id ) );
74 }
75
76 /**
77 * Open an admin URL in an iframe window (an edit screen, a
78 * settings page).
79 *
80 * @param string $url Admin URL.
81 * @param string $title Window title; the page's own title when ''.
82 * @param string $icon Window icon (a Dashicons class or an image
83 * URL); the shell's generic glyph when ''.
84 * @return self
85 */
86 public function open_url( $url, $title = '', $icon = '' ) {
87 return $this->add(
88 'open_url',
89 array(
90 'url' => (string) $url,
91 'title' => (string) $title,
92 'icon' => (string) $icon,
93 )
94 );
95 }
96
97 /**
98 * Set (or clear with 0) the badge on the app's dock tile and
99 * desktop icon.
100 *
101 * @param int $count Count; 0 clears.
102 * @return self
103 */
104 public function badge( $count ) {
105 return $this->add( 'badge', array( 'count' => max( 0, (int) $count ) ) );
106 }
107
108 /**
109 * Swap the art on every rail hosting the app's tile — dock,
110 * taskbar, desktop icon. State-driven icons (the Recycle Bin's
111 * empty/full bin is the canonical case).
112 *
113 * @param string $icon SVG data URI or image URL.
114 * @return self
115 */
116 public function icon( $icon ) {
117 return $this->add( 'icon', array( 'icon' => (string) $icon ) );
118 }
119
120 /**
121 * Announce a content change so every window showing that content
122 * refreshes (`wp.os.announceContentChange`).
123 *
124 * @param string $type Content type, e.g. `post`, `comment`, `user`.
125 * @param string $action `created` | `updated` | `trashed` | `untrashed` | `deleted`.
126 * @param int|int[] $ids Affected ids.
127 * @return self
128 */
129 public function announce( $type, $action, $ids ) {
130 return $this->add(
131 'announce',
132 array(
133 'contentType' => (string) $type,
134 'action' => (string) $action,
135 'ids' => array_values( array_map( 'intval', (array) $ids ) ),
136 )
137 );
138 }
139
140 /**
141 * Pop a context menu at the pointer. Each item dispatches an
142 * action when picked.
143 *
144 * @param array<int,array<string,mixed>> $items Each: `label`, `action` (required), `args`, `icon`, `danger`, `disabled`.
145 * @return self
146 */
147 public function menu( array $items ) {
148 $clean = array();
149 foreach ( $items as $index => $item ) {
150 if ( empty( $item['label'] ) || empty( $item['action'] ) ) {
151 continue;
152 }
153 $clean[] = array(
154 'id' => isset( $item['id'] ) ? (string) $item['id'] : 'item-' . $index,
155 'label' => (string) $item['label'],
156 'action' => (string) $item['action'],
157 'args' => isset( $item['args'] ) && is_array( $item['args'] ) ? $item['args'] : array(),
158 'icon' => isset( $item['icon'] ) ? (string) $item['icon'] : '',
159 'danger' => ! empty( $item['danger'] ),
160 'disabled' => ! empty( $item['disabled'] ),
161 );
162 }
163 return $this->add( 'menu', array( 'items' => $clean ) );
164 }
165
166 /**
167 * Publish on the window's channel bus (`ctx.window.send`), for
168 * peers connected with `wp.os.connect( id )`.
169 *
170 * @param string $channel Channel name.
171 * @param mixed $payload Serialisable payload.
172 * @return self
173 */
174 public function send( $channel, $payload = null ) {
175 return $this->add(
176 'send',
177 array(
178 'channel' => (string) $channel,
179 'payload' => $payload,
180 )
181 );
182 }
183
184 /**
185 * Ask the shell to rebuild its registries from a fresh menu
186 * payload (`wp.os.refreshMenu()`).
187 *
188 * For an action that changed what the SERVER registers — a site
189 * option that gates a whole module, a per-user flag a plugin's
190 * `init` reads. The shell only learns about server registrations
191 * from a payload, and the request that wrote the option decided,
192 * near its own start, what to register: it cannot report the
193 * window it would now add. The refresh is a separate request by
194 * design, which an effect — performed after this response lands —
195 * is exactly.
196 *
197 * @return self
198 */
199 public function refresh_menu() {
200 return $this->add( 'refresh_menu', array() );
201 }
202
203 /**
204 * Queue a custom effect for a runtime extension to handle.
205 *
206 * @param string $type Effect type.
207 * @param array<string,mixed> $data Payload.
208 * @return self
209 */
210 public function add( $type, array $data = array() ) {
211 $this->items[] = array_merge( array( 'type' => (string) $type ), $data );
212 return $this;
213 }
214
215 /**
216 * Everything queued, in order.
217 *
218 * @return array<int,array<string,mixed>>
219 */
220 public function all() {
221 return $this->items;
222 }
223 }
224