Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitfadbf77

Browse files
BrunoQuaresmacode-asher
authored andcommitted
feat: add app iframe controls
1 parent9cbe02e commitfadbf77

File tree

2 files changed

+115
-39
lines changed

2 files changed

+115
-39
lines changed

‎site/src/pages/TaskPage/TaskAppIframe.tsx

Lines changed: 92 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
11
importtype{WorkspaceApp}from"api/typesGenerated";
2+
import{Button}from"components/Button/Button";
3+
import{
4+
DropdownMenu,
5+
DropdownMenuContent,
6+
DropdownMenuItem,
7+
DropdownMenuTrigger,
8+
}from"components/DropdownMenu/DropdownMenu";
9+
import{
10+
EllipsisVertical,
11+
ExternalLinkIcon,
12+
HouseIcon,
13+
RotateCwIcon,
14+
}from"lucide-react";
15+
import{openAppInNewWindow}from"modules/apps/apps";
216
import{useAppLink}from"modules/apps/useAppLink";
317
importtype{Task}from"modules/tasks/tasks";
4-
importtype{FC}from"react";
18+
import{typeFC,useRef}from"react";
519
import{cn}from"utils/cn";
620

721
typeTaskAppIFrameProps={
@@ -31,24 +45,85 @@ export const TaskAppIFrame: FC<TaskAppIFrameProps> = ({
3145
workspace:task.workspace,
3246
});
3347

34-
lethref=link.href;
35-
try{
36-
consturl=newURL(link.href);
37-
if(pathname){
38-
url.pathname=pathname;
48+
constappHref=():string=>{
49+
try{
50+
consturl=newURL(link.href,location.href);
51+
if(pathname){
52+
url.pathname=pathname;
53+
}
54+
returnurl.toString();
55+
}catch(err){
56+
console.warn(`Failed to parse URL${link.href} for app${app.id}`,err);
57+
returnlink.href;
3958
}
40-
href=url.toString();
41-
}catch(err){
42-
console.warn(`Failed to parse URL${link.href} for app${app.id}`,err);
43-
}
59+
};
60+
61+
constframeRef=useRef<HTMLIFrameElement>(null);
62+
constframeSrc=appHref();
4463

4564
return(
46-
<iframe
47-
src={href}
48-
title={link.label}
49-
loading="eager"
50-
className={cn([active ?"block" :"hidden","w-full h-full border-0"])}
51-
allow="clipboard-read; clipboard-write"
52-
/>
65+
<divclassName={cn([active ?"block" :"hidden","w-full h-ful"])}>
66+
<divclassName="bg-surface-tertiary flex items-center p-2 py-1 gap-1">
67+
<Button
68+
size="icon"
69+
variant="subtle"
70+
onClick={(e)=>{
71+
e.preventDefault();
72+
if(frameRef.current?.contentWindow){
73+
frameRef.current.contentWindow.location.reload();
74+
}
75+
}}
76+
>
77+
<RotateCwIcon/>
78+
<spanclassName="sr-only">Refresh</span>
79+
</Button>
80+
81+
<Button
82+
size="icon"
83+
variant="subtle"
84+
onClick={(e)=>{
85+
e.preventDefault();
86+
if(frameRef.current?.contentWindow){
87+
frameRef.current.contentWindow.location.href=appHref();
88+
}
89+
}}
90+
>
91+
<HouseIcon/>
92+
<spanclassName="sr-only">Home</span>
93+
</Button>
94+
95+
{/* Possibly we will put a URL bar here, but for now we cannot due to
96+
* cross-origin restrictions in iframes. */}
97+
<divclassName="w-full"></div>
98+
99+
<DropdownMenu>
100+
<DropdownMenuTriggerasChild>
101+
<Buttonsize="icon"variant="subtle"aria-label="More options">
102+
<EllipsisVerticalaria-hidden="true"/>
103+
<spanclassName="sr-only">More options</span>
104+
</Button>
105+
</DropdownMenuTrigger>
106+
<DropdownMenuContentalign="end">
107+
<DropdownMenuItem
108+
onClick={()=>{
109+
openAppInNewWindow(frameSrc);
110+
}}
111+
>
112+
<ExternalLinkIcon/>
113+
Open app in new tab
114+
</DropdownMenuItem>
115+
</DropdownMenuContent>
116+
</DropdownMenu>
117+
</div>
118+
119+
<iframe
120+
ref={frameRef}
121+
src={frameSrc}
122+
title={link.label}
123+
loading="eager"
124+
className={"w-full h-full border-0"}
125+
allow="clipboard-read; clipboard-write"
126+
/>
127+
</div>
53128
);
54129
};

‎site/src/pages/TaskPage/TaskApps.tsx

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export const TaskApps: FC<TaskAppsProps> = ({ task }) => {
3838
const[activeAppId,setActiveAppId]=useState<string>(()=>{
3939
constappId=embeddedApps[0]?.id;
4040
if(!appId){
41-
thrownewError("Noapps found in task");
41+
thrownewError("Noactive app found in task");
4242
}
4343
returnappId;
4444
});
@@ -57,19 +57,21 @@ export const TaskApps: FC<TaskAppsProps> = ({ task }) => {
5757

5858
return(
5959
<mainclassName="flex-1 flex flex-col">
60-
<divclassName="border-0 border-b border-border border-solid w-full p-1 flex gap-2">
61-
{embeddedApps.map((app)=>(
62-
<TaskAppButton
63-
key={app.id}
64-
task={task}
65-
app={app}
66-
active={app.id===activeAppId}
67-
onClick={(e)=>{
68-
e.preventDefault();
69-
setActiveAppId(app.id);
70-
}}
71-
/>
72-
))}
60+
<divclassName="w-full flex items-center border-0 border-b border-border border-solid">
61+
<divclassName=" p-2 pb-0 flex gap-2 items-center">
62+
{embeddedApps.map((app)=>(
63+
<TaskAppTab
64+
key={app.id}
65+
task={task}
66+
app={app}
67+
active={app.id===activeAppId}
68+
onClick={(e)=>{
69+
e.preventDefault();
70+
setActiveAppId(app.id);
71+
}}
72+
/>
73+
))}
74+
</div>
7375

7476
{externalApps.length>0&&(
7577
<divclassName="ml-auto">
@@ -122,19 +124,14 @@ export const TaskApps: FC<TaskAppsProps> = ({ task }) => {
122124
);
123125
};
124126

125-
typeTaskAppButtonProps={
127+
typeTaskAppTabProps={
126128
task:Task;
127129
app:WorkspaceApp;
128130
active:boolean;
129131
onClick:(e:React.MouseEvent<HTMLAnchorElement>)=>void;
130132
};
131133

132-
constTaskAppButton:FC<TaskAppButtonProps>=({
133-
task,
134-
app,
135-
active,
136-
onClick,
137-
})=>{
134+
constTaskAppTab:FC<TaskAppTabProps>=({ task, app, active, onClick})=>{
138135
constagent=task.workspace.latest_build.resources
139136
.flatMap((r)=>r.agents)
140137
.filter((a)=>!!a)
@@ -156,7 +153,11 @@ const TaskAppButton: FC<TaskAppButtonProps> = ({
156153
key={app.id}
157154
asChild
158155
className={cn([
159-
{"text-content-primary":active},
156+
"px-3",
157+
{
158+
"text-content-primary bg-surface-tertiary rounded-sm rounded-b-none":
159+
active,
160+
},
160161
{"opacity-75 hover:opacity-100":!active},
161162
])}
162163
>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp