@@ -2,13 +2,18 @@ import * as domloaded from 'dom-loaded';
2
2
import * as select from 'select-dom' ;
3
3
import { ConfigProvider } from '../config' ;
4
4
import { ButtonInjector , InjectorBase , checkIsBtnUpToDate , rewritePeriodKeybindGitLab } from './injector' ;
5
- import { renderGitpodUrl , makeOpenInPopup , UrlInfo } from '../utils' ;
5
+ import { renderGitpodUrl , makeOpenInPopup , UrlInfo , renderGitpodCustomEditor , createElementFromHTML , ideOptions } from '../utils' ;
6
+ import { IDEOptions } from '@gitpod/gitpod-protocol/lib/ide-protocol' ;
6
7
7
8
namespace Gitpodify {
8
9
export const BTN_ID = "gitpod-btn-nav" ;
9
10
export const BTN_CLASS = "gitpod-nav-btn" ;
10
11
}
11
12
13
+
14
+ const DropdownID = "gitpod-dropdown"
15
+ const DropdownTriggerID = "gitpod-dropdown-trigger"
16
+
12
17
export class GitlabInjector extends InjectorBase {
13
18
14
19
constructor ( protected readonly configProvider : ConfigProvider ) {
@@ -49,6 +54,7 @@ export class GitlabInjector extends InjectorBase {
49
54
50
55
class RepositoryInjector implements ButtonInjector {
51
56
static readonly PARENT_SELECTOR = ".tree-controls" ;
57
+ protected showDropdown : boolean = false ;
52
58
53
59
isApplicableToCurrentPage ( ) : boolean {
54
60
const result = ! ! select . exists ( RepositoryInjector . PARENT_SELECTOR )
@@ -71,8 +77,9 @@ class RepositoryInjector implements ButtonInjector {
71
77
return ;
72
78
}
73
79
74
- const btn = this . renderButton ( currentUrl , openAsPopup ) ;
80
+ const btn = this . renderButton ( urlInfo , openAsPopup , useLatest ) ;
75
81
parent . firstElementChild . appendChild ( btn ) ;
82
+ this . bindDropdown ( )
76
83
77
84
const primaryButtons = parent . firstElementChild . getElementsByClassName ( "btn-primary" ) ;
78
85
if ( primaryButtons && primaryButtons . length > 1 ) {
@@ -85,27 +92,103 @@ class RepositoryInjector implements ButtonInjector {
85
92
}
86
93
}
87
94
88
- protected renderButton ( url : string , openAsPopup : boolean ) : HTMLElement {
89
- const container = document . createElement ( 'div' ) ;
90
- container . className = "project-clone-holder d-none d-md-inline-block" ;
95
+ genOptionsString ( ideOptions : IDEOptions , urlInfo : UrlInfo , useLatest : boolean ) {
96
+ if ( ! ideOptions . clients ) {
97
+ return [ ]
98
+ }
99
+ return Object . entries ( ideOptions . options ?? { } ) . map ( ( [ ide , ideOption ] ) => {
100
+ const url = renderGitpodCustomEditor ( urlInfo . host , urlInfo . originUrl , ide , useLatest ) ;
101
+ const title = ideOption . title + ( ideOption . type === "desktop" ? "" : ( " - " + ideOption . type . toUpperCase ( ) ) ) ;
102
+ const logo = ideOption . logo
103
+ return `<li role="presentation" class="gl-new-dropdown-item"><button data-qa-selector="webide_menu_item"
104
+ data-testid="action_webide" role="menuitem" type="button" class="dropdown-item">
105
+ <img class="gl-icon s16 gl-new-dropdown-item-check-icon gl-mt-3 gl-align-self-start" height="14" width="14" class="octicon octicon-check select-menu-item-icon" src="${ logo } " alt="logo">
106
+ <a class="dropdown-item dropdown-item open-with-link" style="padding: 0;" href="${ url } ">
107
+ <div class="gl-new-dropdown-item-text-wrapper">
108
+ <p class="gl-new-dropdown-item-text-primary"><span
109
+ class="gl-font-weight-bold">${ title } </span></p>
110
+ </div>
111
+ </a>
112
+ </button></li>`
113
+ } )
114
+ }
91
115
92
- const container2ndLevel = document . createElement ( 'div' ) ;
93
- container2ndLevel . className = "git-clone-holder js-git-clone-holder" ;
116
+ bindDropdown ( ) {
117
+ const element = document . querySelector ( '#' + DropdownTriggerID ) as HTMLButtonElement
118
+ if ( element == null ) {
119
+ return
120
+ }
121
+ element . onblur = ( ) => { this . triggerDropdown ( ) }
122
+ element . onfocus = ( ) => { this . triggerDropdown ( ) }
123
+ }
94
124
95
- const a = document . createElement ( 'a' ) ;
96
- a . id = Gitpodify . BTN_ID ;
97
- a . title = "Gitpod" ;
98
- a . text = "Gitpod"
99
- a . href = url ;
100
- a . target = "_blank" ;
101
- a . className = "gl-button btn btn-info" ;
125
+ triggerDropdown ( ) {
126
+ const element = document . querySelector ( '#' + DropdownID )
127
+ const show = ! element ?. classList . contains ( "show" )
128
+ if ( show ) {
129
+ element ?. classList . add ( "show" )
130
+ } else {
131
+ element ?. classList . remove ( "show" )
132
+ }
133
+ this . showDropdown = show
134
+ }
135
+
136
+ protected renderButton ( urlInfo : UrlInfo , openAsPopup : boolean , useLatest : boolean ) {
137
+ const element = createElementFromHTML ( `
138
+ <div class="dropdown b-dropdown gl-new-dropdown btn-group" data-qa-selector="action_dropdown" id="GP_DROPDOWN">
139
+ <a id="GP_DROPDOWN__BV_button_" type="button" href="${ urlInfo . gitpodUrl } "
140
+ class="btn btn-default btn-md gl-button split-content-button btn-default-secondary">
141
+ <span
142
+ data-qa-selector="gitpod_button" class="gl-new-dropdown-button-text">
143
+ Gitpod
144
+ </span>
145
+ </a>
146
+ <button id="${ DropdownTriggerID } " aria-haspopup="true" aria-expanded="true" type="button"
147
+ class="btn dropdown-toggle btn-default btn-md gl-button gl-dropdown-toggle btn-default-secondary dropdown-toggle-split"
148
+ id="GP_DROPDOWN__BV_toggle_">
149
+ <span class="sr-only">Toggle dropdown</span>
150
+ </button>
151
+ <ul id="${ DropdownID } " role="menu" tabindex="-1" class="dropdown-menu" aria-labelledby="GP_DROPDOWN__BV_button_"
152
+ style="position: absolute; transform: translate3d(-144px, 32px, 0px); top: 0px; left: 0px; will-change: transform;"
153
+ x-placement="bottom-start">
154
+ <div class="gl-new-dropdown-inner">
155
+ <label class="px-2 label-bold">Open with</label>
156
+ <div class="gl-new-dropdown-contents">
157
+ ${ this . genOptionsString ( ideOptions , urlInfo , useLatest ) . join ( "\n" ) }
158
+ </div>
159
+ </div>
160
+ </ul>
161
+ </div>` )
102
162
103
163
if ( openAsPopup ) {
104
- makeOpenInPopup ( a ) ;
164
+ element . querySelectorAll ( 'a' ) . forEach ( e => {
165
+ makeOpenInPopup ( e ) ;
166
+ } ) ;
105
167
}
106
-
107
- container2ndLevel . appendChild ( a ) ;
108
- container . appendChild ( container2ndLevel ) ;
109
- return container ;
168
+ return element
110
169
}
170
+
171
+ // protected renderButton(url: string, openAsPopup: boolean): HTMLElement {
172
+ // const container = document.createElement('div');
173
+ // container.className = "project-clone-holder d-none d-md-inline-block";
174
+
175
+ // const container2ndLevel = document.createElement('div');
176
+ // container2ndLevel.className = "git-clone-holder js-git-clone-holder";
177
+
178
+ // const a = document.createElement('a');
179
+ // a.id = Gitpodify.BTN_ID;
180
+ // a.title = "Gitpod";
181
+ // a.text = "Gitpod"
182
+ // a.href = url;
183
+ // a.target = "_blank";
184
+ // a.className = "gl-button btn btn-info";
185
+
186
+ // if (openAsPopup) {
187
+ // makeOpenInPopup(a);
188
+ // }
189
+
190
+ // container2ndLevel.appendChild(a);
191
+ // container.appendChild(container2ndLevel);
192
+ // return container;
193
+ // }
111
194
}
0 commit comments