Skip to content

Commit 9fc1737

Browse files
committed
Apps can work in panels or browser tabs
1 parent aaa3091 commit 9fc1737

23 files changed

+1162
-261
lines changed

directory/local-conformance-2_0.v2.json

+847
Large diffs are not rendered by default.

package-lock.json

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"@kite9/client": "2.2.0-beta.6",
2222
"@kite9/da-server": "2.2.0-beta.6",
2323
"@kite9/fdc3": "2.2.0-beta.6",
24+
"@kite9/fdc3-common": "2.2.0-beta.6",
2425
"@types/react-dom": "^18.2.25",
2526
"@types/uuid": "^9.0.8",
2627
"@types/ws": "^8.5.10",

src/app/app1.ts

-34
This file was deleted.

src/app/util.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import { FDC3_APP_EVENT, FDC3_DA_EVENT } from "../server/da/message-types"
55

66
export function link(socket: Socket, channel: MessageChannel, source: InstanceID) {
77
socket.on(FDC3_DA_EVENT, (data: any, to: InstanceID) => {
8-
console.log(`DA Sent ${JSON.stringify(data)} from socket`)
8+
//console.log(`DA Sent ${JSON.stringify(data)} from socket`)
99
channel.port2.postMessage(data)
1010
})
1111

1212
channel.port2.onmessage = function (event) {
13-
console.log(`App Sent ${JSON.stringify(event.data)} from message port`)
13+
//console.log(`App Sent ${JSON.stringify(event.data)} from message port`)
1414
socket.emit(FDC3_APP_EVENT, event.data, source)
1515
}
1616
}

src/client/appd/appd.tsx

+14-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { Component } from "react";
22
import { Icon } from "../icon/icon";
3-
import { getServerState } from "../state/serverConnectivity";
3+
import { getServerState } from "../state/ServerState";
44
import * as styles from "./styles.module.css";
55
import { Popup, PopupButton } from "../popups/popup";
66
import { DirectoryApp } from "@kite9/da-server";
7+
import { getAppState } from "../state/AppState";
78

89
const DEFAULT_ICON = "/static/icons/control/choose-app.svg";
910

@@ -39,13 +40,13 @@ export class AppDPanel extends Component<AppPanelProps, AppPanelState> {
3940
//console.log("loaded - ready to display")
4041
this.setState({
4142
chosen: null,
42-
apps,
43+
apps: apps.filter((d) => onlyRelevantApps(d)),
4344
});
4445
});
4546
};
4647

4748
setChosen(app: DirectoryApp) {
48-
console.log("state changed " + app.appId);
49+
//console.log("state changed " + app.appId);
4950
this.setState({
5051
apps: this.state.apps,
5152
chosen: app,
@@ -81,7 +82,7 @@ export class AppDPanel extends Component<AppPanelProps, AppPanelState> {
8182
<ul>{app.categories?.map((c: any) => <li>{c}</li>)}</ul>
8283
<div className={styles.appDScreenshots}>
8384
{app.screenshots?.map((s: any) => (
84-
<img src={s.src} title={s.label} />
85+
<img key={s.src} src={s.src} title={s.label} />
8586
))}
8687
</div>
8788
</div>
@@ -91,11 +92,12 @@ export class AppDPanel extends Component<AppPanelProps, AppPanelState> {
9192
}
9293
buttons={[
9394
<PopupButton
95+
key="open"
9496
text="open"
9597
disabled={this.state.chosen == null}
9698
onClick={async () => {
9799
if (this.state.chosen) {
98-
getServerState().registerAppLaunch(this.state.chosen.appId);
100+
getAppState().open(this.state.chosen);
99101
this.props.closeAction();
100102
}
101103
}}
@@ -106,3 +108,10 @@ export class AppDPanel extends Component<AppPanelProps, AppPanelState> {
106108
);
107109
}
108110
}
111+
function onlyRelevantApps(d: DirectoryApp): boolean {
112+
const sail = d.hostManifests?.sail;
113+
const show = sail ? sail.searchable != false : true;
114+
const type = d.type == "web";
115+
const url = d.details?.url;
116+
return show && type && url;
117+
}

src/client/appd/styles.module.css

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
display: flex;
33
flex-direction: row;
44
gap: 1rem;
5+
width: 60rem;
6+
height: 30rem;
57
}
68

79
.appDApps {
@@ -21,6 +23,7 @@
2123
flex-basis: 7.5rem;
2224
flex-grow: 0;
2325
flex-shrink: 0;
26+
max-height: 7.5rem;
2427
display: flex;
2528
flex-direction: column;
2629
justify-content: center;

src/client/frame/frame.tsx

+3-14
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@ import { AppDPanel } from "../appd/appd";
88
import { Content, Grids } from "../grid/grid";
99
import { GridsStateImpl, GridsState } from "../grid/gridstate";
1010
import { ConfigPanel } from "../config/config";
11-
import {
12-
EXAMPLE_APP_INTENTS,
13-
EXAMPLE_CONTEXT,
14-
ResolverPanel,
15-
} from "../resolver/resolver";
11+
import { ResolverPanel } from "../resolver/resolver";
1612

1713
enum Popup {
1814
NONE,
@@ -57,15 +53,6 @@ export class Frame extends Component<FrameProps, FrameState> {
5753
<div className={styles.left}>
5854
<Tabs cs={this.props.cs} />
5955
<Controls>
60-
<Resolver
61-
onClick={() => {
62-
this.props.cs.setIntentResolution({
63-
appIntents: EXAMPLE_APP_INTENTS,
64-
context: EXAMPLE_CONTEXT,
65-
requestId: "123",
66-
});
67-
}}
68-
/>
6956
<NewPanel onClick={() => this.setState({ popup: Popup.APPD })} />
7057
<Bin />
7158
</Controls>
@@ -88,6 +75,7 @@ export class Frame extends Component<FrameProps, FrameState> {
8875
) : null}
8976
{this.state?.popup == Popup.SETTINGS ? (
9077
<ConfigPanel
78+
key="config"
9179
cs={this.props.cs}
9280
closeAction={() =>
9381
this.setState({
@@ -98,6 +86,7 @@ export class Frame extends Component<FrameProps, FrameState> {
9886
) : null}
9987
{this.props.cs.getIntentResolution() ? (
10088
<ResolverPanel
89+
key="resolver"
10190
cs={this.props.cs}
10291
appIntents={this.props.cs.getIntentResolution()!!.appIntents}
10392
context={this.props.cs.getIntentResolution()!!.context}

src/client/grid/grid.tsx

+25-10
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@ import { AppPanel, ClientState } from "../state/clientState";
33
import * as styles from "./styles.module.css";
44
import "gridstack/dist/gridstack.css";
55
import { GridsState } from "./gridstate";
6+
import { getAppState } from "../state/AppState";
67

78
type GridsProps = { cs: ClientState; gs: GridsState; id: string };
89

910
export class Grids extends Component<GridsProps> {
1011
componentDidMount(): void {
11-
console.log("CDM");
1212
this.componentDidUpdate();
1313
}
1414

1515
componentDidUpdate(): void {
16-
console.log("CDU");
1716
this.props.gs.updatePanels();
1817
}
1918

@@ -32,10 +31,20 @@ const AppFrame = ({ panel }: { panel: AppPanel }) => {
3231
return (
3332
<iframe
3433
src={panel.url}
35-
id={"iframe_" + panel.id}
36-
name={panel.id}
37-
slot={"slot_" + panel.id}
34+
id={"iframe_" + panel.panelId}
35+
name={panel.panelId}
36+
slot={"slot_" + panel.panelId}
3837
className={styles.iframe}
38+
ref={(ref) => {
39+
setTimeout(() => {
40+
// this is a bit hacky but we need to track the window objects
41+
// in the app state so we make sure we know who we're talking to
42+
if (ref) {
43+
const contentWindow = (ref as HTMLIFrameElement).contentWindow;
44+
getAppState().registerAppWindow(contentWindow!!, panel.panelId);
45+
}
46+
}, 10);
47+
}}
3948
/>
4049
);
4150
};
@@ -50,12 +59,13 @@ const LockIcon = () => {
5059
);
5160
};
5261

53-
const PopOutIcon = () => {
62+
const PopOutIcon = ({ action }: { action: () => void }) => {
5463
return (
5564
<img
5665
src="/static/icons/control/pop-out.svg"
5766
className={styles.contentTitleIcon}
5867
title="Pop Out"
68+
onClick={() => action()}
5969
/>
6070
);
6171
};
@@ -73,8 +83,8 @@ const CloseIcon = ({ action }: { action: () => void }) => {
7383

7484
const AppSlot = ({ panel }: { panel: AppPanel }) => {
7585
return (
76-
<div id={"app_" + panel.id}>
77-
<slot name={"slot_" + panel.id} />
86+
<div id={"app_" + panel.panelId}>
87+
<slot name={"slot_" + panel.panelId} />
7888
</div>
7989
);
8090
};
@@ -92,12 +102,17 @@ export const Content = ({
92102
<div className={styles.content} id={id}>
93103
<div className={styles.contentInner}>
94104
<div className={styles.contentTitle}>
95-
<CloseIcon action={() => cs.removePanel(panel.id)} />
105+
<CloseIcon action={() => cs.removePanel(panel.panelId)} />
96106
<p className={styles.contentTitleText}>
97107
<span className={styles.contentTitleTextSpan}>{panel.title}</span>
98108
</p>
99109
<LockIcon />
100-
<PopOutIcon />
110+
<PopOutIcon
111+
action={() => {
112+
cs.removePanel(panel.panelId);
113+
window.open(panel.url, "_blank");
114+
}}
115+
/>
101116
</div>
102117
<div className={styles.contentBody}>
103118
{panel.url ? <AppSlot panel={panel} /> : <div />}

0 commit comments

Comments
 (0)