11import * as path from 'vs/base/common/path' ;
2- import { URI } from 'vs/base/common/uri' ;
32import { Options } from 'vs/ipc' ;
43import { localize } from 'vs/nls' ;
4+ import { MenuId , MenuRegistry } from 'vs/platform/actions/common/actions' ;
5+ import { CommandsRegistry } from 'vs/platform/commands/common/commands' ;
56import { Extensions , IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry' ;
7+ import { ContextKeyExpr , IContextKeyService } from 'vs/platform/contextkey/common/contextkey' ;
68import { registerSingleton } from 'vs/platform/instantiation/common/extensions' ;
79import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection' ;
810import { ILogService } from 'vs/platform/log/common/log' ;
@@ -11,10 +13,18 @@ import { Registry } from 'vs/platform/registry/common/platform';
1113import { IStorageService , StorageScope , StorageTarget } from 'vs/platform/storage/common/storage' ;
1214import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry' ;
1315import { TelemetryChannelClient } from 'vs/server/common/telemetry' ;
16+ import { getOptions } from 'vs/server/common/util' ;
1417import 'vs/workbench/contrib/localizations/browser/localizations.contribution' ;
1518import 'vs/workbench/services/localizations/browser/localizationsService' ;
1619import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService' ;
1720
21+ /**
22+ * All client-side customization to VS Code should live in this file when
23+ * possible.
24+ */
25+
26+ const options = getOptions < Options > ( ) ;
27+
1828class TelemetryService extends TelemetryChannelClient {
1929 public constructor (
2030 @IRemoteAgentService remoteAgentService : IRemoteAgentService ,
@@ -23,26 +33,6 @@ class TelemetryService extends TelemetryChannelClient {
2333 }
2434}
2535
26- /**
27- * Remove extra slashes in a URL.
28- */
29- export const normalize = ( url : string , keepTrailing = false ) : string => {
30- return url . replace ( / \/ \/ + / g, '/' ) . replace ( / \/ + $ / , keepTrailing ? '/' : '' ) ;
31- } ;
32-
33- /**
34- * Get options embedded in the HTML.
35- */
36- export const getOptions = < T extends Options > ( ) : T => {
37- try {
38- return JSON . parse ( document . getElementById ( 'coder-options' ) ! . getAttribute ( 'data-settings' ) ! ) ;
39- } catch ( error ) {
40- return { } as T ;
41- }
42- } ;
43-
44- const options = getOptions ( ) ;
45-
4636const TELEMETRY_SECTION_ID = 'telemetry' ;
4737Registry . as < IConfigurationRegistry > ( Extensions . Configuration ) . registerConfiguration ( {
4838 'id' : TELEMETRY_SECTION_ID ,
@@ -173,38 +163,36 @@ export const initialize = async (services: ServiceCollection): Promise<void> =>
173163 if ( theme ) {
174164 localStorage . setItem ( 'colorThemeData' , theme ) ;
175165 }
176- } ;
177166
178- export interface Query {
179- [ key : string ] : string | undefined ;
180- }
181-
182- /**
183- * Split a string up to the delimiter. If the delimiter doesn't exist the first
184- * item will have all the text and the second item will be an empty string.
185- */
186- export const split = ( str : string , delimiter : string ) : [ string , string ] => {
187- const index = str . indexOf ( delimiter ) ;
188- return index !== - 1 ? [ str . substring ( 0 , index ) . trim ( ) , str . substring ( index + 1 ) ] : [ str , '' ] ;
189- } ;
167+ // Use to show or hide logout commands and menu options.
168+ const contextKeyService = ( services . get ( IContextKeyService ) as IContextKeyService ) ;
169+ contextKeyService . createKey ( 'code-server.authed' , options . authed ) ;
170+
171+ // Add a logout command.
172+ const logoutEndpoint = path . join ( options . base , '/logout' ) + `?base=${ options . base } ` ;
173+ const LOGOUT_COMMAND_ID = 'code-server.logout' ;
174+ CommandsRegistry . registerCommand (
175+ LOGOUT_COMMAND_ID ,
176+ ( ) => {
177+ window . location . href = logoutEndpoint ;
178+ } ,
179+ ) ;
180+
181+ // Add logout to command palette.
182+ MenuRegistry . appendMenuItem ( MenuId . CommandPalette , {
183+ command : {
184+ id : LOGOUT_COMMAND_ID ,
185+ title : localize ( 'logout' , "Log out" )
186+ } ,
187+ when : ContextKeyExpr . has ( 'code-server.authed' )
188+ } ) ;
190189
191- /**
192- * Return the URL modified with the specified query variables. It's pretty
193- * stupid so it probably doesn't cover any edge cases. Undefined values will
194- * unset existing values. Doesn't allow duplicates.
195- */
196- export const withQuery = ( url : string , replace : Query ) : string => {
197- const uri = URI . parse ( url ) ;
198- const query = { ...replace } ;
199- uri . query . split ( '&' ) . forEach ( ( kv ) => {
200- const [ key , value ] = split ( kv , '=' ) ;
201- if ( ! ( key in query ) ) {
202- query [ key ] = value ;
203- }
190+ // Add logout to the (web-only) home menu.
191+ MenuRegistry . appendMenuItem ( MenuId . MenubarHomeMenu , {
192+ command : {
193+ id : LOGOUT_COMMAND_ID ,
194+ title : localize ( 'logout' , "Log out" )
195+ } ,
196+ when : ContextKeyExpr . has ( 'code-server.authed' )
204197 } ) ;
205- return uri . with ( {
206- query : Object . keys ( query )
207- . filter ( ( k ) => typeof query [ k ] !== 'undefined' )
208- . map ( ( k ) => `${ k } =${ query [ k ] } ` ) . join ( '&' ) ,
209- } ) . toString ( true ) ;
210198} ;
0 commit comments