2012-01-18 21:21:56 -05:00
const Gettext = imports . gettext ;
2019-02-08 22:21:36 -05:00
const { Gdk , GLib , Gio , GObject , Gtk , Pango } = imports . gi ;
2012-05-04 17:23:08 -04:00
const Format = imports . format ;
2012-01-18 21:21:56 -05:00
const _ = Gettext . gettext ;
const Config = imports . misc . config ;
const ExtensionUtils = imports . misc . extensionUtils ;
2018-09-05 20:55:20 -04:00
const { loadInterfaceXML } = imports . misc . fileUtils ;
2012-01-18 21:21:56 -05:00
2018-09-05 20:55:20 -04:00
const GnomeShellIface = loadInterfaceXML ( 'org.gnome.Shell.Extensions' ) ;
2012-01-18 21:21:56 -05:00
const GnomeShellProxy = Gio . DBusProxy . makeProxyWrapper ( GnomeShellIface ) ;
function stripPrefix ( string , prefix ) {
if ( string . slice ( 0 , prefix . length ) == prefix )
return string . slice ( prefix . length ) ;
return string ;
}
2017-10-30 21:19:44 -04:00
var Application = class {
constructor ( ) {
2012-01-18 21:21:56 -05:00
GLib . set _prgname ( 'gnome-shell-extension-prefs' ) ;
this . application = new Gtk . Application ( {
application _id : 'org.gnome.shell.ExtensionPrefs' ,
flags : Gio . ApplicationFlags . HANDLES _COMMAND _LINE
} ) ;
2017-12-01 19:27:35 -05:00
this . application . connect ( 'activate' , this . _onActivate . bind ( this ) ) ;
this . application . connect ( 'command-line' , this . _onCommandLine . bind ( this ) ) ;
this . application . connect ( 'startup' , this . _onStartup . bind ( this ) ) ;
2012-01-18 21:21:56 -05:00
this . _extensionPrefsModules = { } ;
2013-02-28 08:50:56 -05:00
this . _startupUuid = null ;
2014-05-26 19:36:41 -04:00
this . _loaded = false ;
this . _skipMainWindow = false ;
2017-10-30 21:19:44 -04:00
}
2012-01-18 21:21:56 -05:00
2017-10-30 20:03:21 -04:00
_extensionAvailable ( uuid ) {
2012-01-30 20:58:29 -05:00
let extension = ExtensionUtils . extensions [ uuid ] ;
2012-01-18 21:21:56 -05:00
2012-01-30 20:58:29 -05:00
if ( ! extension )
2012-01-18 21:21:56 -05:00
return false ;
2012-01-30 20:58:29 -05:00
if ( ! extension . dir . get _child ( 'prefs.js' ) . query _exists ( null ) )
2012-01-18 21:21:56 -05:00
return false ;
return true ;
2017-10-30 21:19:44 -04:00
}
2012-01-18 21:21:56 -05:00
2017-10-30 20:03:21 -04:00
_getExtensionPrefsModule ( extension ) {
2012-01-30 20:58:29 -05:00
let uuid = extension . metadata . uuid ;
2012-01-18 21:21:56 -05:00
2012-01-30 20:58:29 -05:00
if ( this . _extensionPrefsModules . hasOwnProperty ( uuid ) )
return this . _extensionPrefsModules [ uuid ] ;
2012-01-18 21:21:56 -05:00
2012-01-30 20:58:29 -05:00
ExtensionUtils . installImporter ( extension ) ;
2012-01-18 21:21:56 -05:00
2012-01-30 20:58:29 -05:00
let prefsModule = extension . imports . prefs ;
prefsModule . init ( extension . metadata ) ;
this . _extensionPrefsModules [ uuid ] = prefsModule ;
2012-01-18 21:21:56 -05:00
return prefsModule ;
2017-10-30 21:19:44 -04:00
}
2012-01-18 21:21:56 -05:00
2017-10-30 20:03:21 -04:00
_selectExtension ( uuid ) {
2012-01-18 21:21:56 -05:00
if ( ! this . _extensionAvailable ( uuid ) )
return ;
2012-01-30 20:58:29 -05:00
let extension = ExtensionUtils . extensions [ uuid ] ;
2012-01-18 21:21:56 -05:00
let widget ;
try {
2012-01-30 20:58:29 -05:00
let prefsModule = this . _getExtensionPrefsModule ( extension ) ;
widget = prefsModule . buildPrefsWidget ( ) ;
2012-01-18 21:21:56 -05:00
} catch ( e ) {
2012-01-30 20:58:29 -05:00
widget = this . _buildErrorUI ( extension , e ) ;
2012-01-18 21:21:56 -05:00
}
2017-04-20 11:00:10 -04:00
let dialog = new Gtk . Window ( { modal : ! this . _skipMainWindow ,
type _hint : Gdk . WindowTypeHint . DIALOG } ) ;
dialog . set _titlebar ( new Gtk . HeaderBar ( { show _close _button : true ,
title : extension . metadata . name ,
visible : true } ) ) ;
2014-05-26 19:36:41 -04:00
if ( this . _skipMainWindow ) {
this . application . add _window ( dialog ) ;
if ( this . _window )
this . _window . destroy ( ) ;
this . _window = dialog ;
this . _window . window _position = Gtk . WindowPosition . CENTER ;
} else {
dialog . transient _for = this . _window ;
}
2014-05-22 22:49:37 -04:00
dialog . set _default _size ( 600 , 400 ) ;
2017-04-20 11:00:10 -04:00
dialog . add ( widget ) ;
2014-05-22 22:49:37 -04:00
dialog . show ( ) ;
2017-10-30 21:19:44 -04:00
}
2012-01-18 21:21:56 -05:00
2017-10-30 20:03:21 -04:00
_buildErrorUI ( extension , exc ) {
2018-08-05 22:15:12 -04:00
let scroll = new Gtk . ScrolledWindow ( {
hscrollbar _policy : Gtk . PolicyType . NEVER ,
propagate _natural _height : true
} ) ;
let box = new Gtk . Box ( {
orientation : Gtk . Orientation . VERTICAL ,
spacing : 12 ,
margin : 100 ,
margin _bottom : 60
} ) ;
scroll . add ( box ) ;
2012-01-18 21:21:56 -05:00
let label = new Gtk . Label ( {
2019-02-01 14:11:39 -05:00
label : '<span size="x-large">%s</span>' . format ( _ ( "Something’ s gone wrong" ) ) ,
2018-08-05 22:15:12 -04:00
use _markup : true
} ) ;
label . get _style _context ( ) . add _class ( Gtk . STYLE _CLASS _DIM _LABEL ) ;
box . add ( label ) ;
label = new Gtk . Label ( {
label : _ ( "We’ re very sorry, but there’ s been a problem: the settings for this extension can’ t be displayed. We recommend that you report the issue to the extension authors." ) ,
justify : Gtk . Justification . CENTER ,
wrap : true
2012-01-18 21:21:56 -05:00
} ) ;
box . add ( label ) ;
2018-08-05 22:15:12 -04:00
let expander = new Expander ( {
label : _ ( "Technical Details" ) ,
margin _top : 12
} ) ;
box . add ( expander ) ;
2012-01-18 21:21:56 -05:00
2018-08-05 22:15:12 -04:00
let errortext = ` ${ exc } \n \n Stack trace: \n ${
// Indent stack trace.
exc . stack . split ( '\n' ) . map ( line => ` ${ line } ` ) . join ( '\n' )
} ` ;
2012-01-18 21:21:56 -05:00
let buffer = new Gtk . TextBuffer ( { text : errortext } ) ;
2018-08-05 22:15:12 -04:00
let textview = new Gtk . TextView ( {
buffer : buffer ,
wrap _mode : Gtk . WrapMode . WORD ,
monospace : true ,
editable : false ,
top _margin : 12 ,
bottom _margin : 12 ,
left _margin : 12 ,
right _margin : 12
} ) ;
let toolbar = new Gtk . Toolbar ( ) ;
let provider = new Gtk . CssProvider ( ) ;
provider . load _from _data ( ` * {
border : 0 solid @ borders ;
border - top - width : 1 px ;
} ` );
toolbar . get _style _context ( ) . add _provider (
provider ,
Gtk . STYLE _PROVIDER _PRIORITY _APPLICATION
) ;
let copyButton = new Gtk . ToolButton ( {
icon _name : 'edit-copy-symbolic' ,
tooltip _text : _ ( "Copy Error" )
} ) ;
toolbar . add ( copyButton ) ;
copyButton . connect ( 'clicked' , w => {
let clipboard = Gtk . Clipboard . get _default ( w . get _display ( ) ) ;
2019-02-12 09:16:08 -05:00
// markdown for pasting in gitlab issues
let lines = [
` The settings of extension ${ extension . uuid } had an error: ` ,
'```' ,
` ${ exc } ` ,
'```' ,
'' ,
'Stack trace:' ,
'```' ,
exc . stack . replace ( /\n$/ , '' ) , // stack without trailing newline
'```' ,
''
] ;
clipboard . set _text ( lines . join ( '\n' ) , - 1 ) ;
2018-08-05 22:15:12 -04:00
} ) ;
2012-01-18 21:21:56 -05:00
2018-08-05 22:15:12 -04:00
let spacing = new Gtk . SeparatorToolItem ( { draw : false } ) ;
toolbar . add ( spacing ) ;
toolbar . child _set _property ( spacing , "expand" , true ) ;
let urlButton = new Gtk . ToolButton ( {
label : _ ( "Homepage" ) ,
tooltip _text : _ ( "Visit extension homepage" ) ,
no _show _all : true ,
visible : extension . metadata . url != null
} ) ;
toolbar . add ( urlButton ) ;
urlButton . connect ( 'clicked' , w => {
let context = w . get _display ( ) . get _app _launch _context ( ) ;
Gio . AppInfo . launch _default _for _uri ( extension . metadata . url , context ) ;
} ) ;
let expandedBox = new Gtk . Box ( {
orientation : Gtk . Orientation . VERTICAL
} ) ;
expandedBox . add ( textview ) ;
expandedBox . add ( toolbar ) ;
expander . add ( expandedBox ) ;
scroll . show _all ( ) ;
return scroll ;
2017-10-30 21:19:44 -04:00
}
2012-01-18 21:21:56 -05:00
2017-10-30 20:03:21 -04:00
_buildUI ( app ) {
2012-01-18 21:21:56 -05:00
this . _window = new Gtk . ApplicationWindow ( { application : app ,
2014-05-22 22:49:37 -04:00
window _position : Gtk . WindowPosition . CENTER } ) ;
2012-01-18 21:21:56 -05:00
2015-12-14 18:37:47 -05:00
this . _window . set _default _size ( 800 , 500 ) ;
2012-01-18 21:21:56 -05:00
2014-05-22 22:49:37 -04:00
this . _titlebar = new Gtk . HeaderBar ( { show _close _button : true ,
2015-12-14 18:37:47 -05:00
title : _ ( "Shell Extensions" ) } ) ;
2014-05-22 22:49:37 -04:00
this . _window . set _titlebar ( this . _titlebar ) ;
2012-01-18 21:21:56 -05:00
2015-12-14 18:15:33 -05:00
let killSwitch = new Gtk . Switch ( { valign : Gtk . Align . CENTER } ) ;
this . _titlebar . pack _end ( killSwitch ) ;
this . _settings = new Gio . Settings ( { schema _id : 'org.gnome.shell' } ) ;
this . _settings . bind ( 'disable-user-extensions' , killSwitch , 'active' ,
2017-04-20 11:09:18 -04:00
Gio . SettingsBindFlags . DEFAULT |
2015-12-14 18:15:33 -05:00
Gio . SettingsBindFlags . INVERT _BOOLEAN ) ;
2018-08-05 20:31:18 -04:00
this . _mainStack = new Gtk . Stack ( {
transition _type : Gtk . StackTransitionType . CROSSFADE
} ) ;
this . _window . add ( this . _mainStack ) ;
2015-12-14 18:37:47 -05:00
let scroll = new Gtk . ScrolledWindow ( { hscrollbar _policy : Gtk . PolicyType . NEVER } ) ;
2012-01-18 21:21:56 -05:00
2014-05-22 22:49:37 -04:00
this . _extensionSelector = new Gtk . ListBox ( { selection _mode : Gtk . SelectionMode . NONE } ) ;
2017-12-01 19:27:35 -05:00
this . _extensionSelector . set _sort _func ( this . _sortList . bind ( this ) ) ;
this . _extensionSelector . set _header _func ( this . _updateHeader . bind ( this ) ) ;
2012-01-18 21:21:56 -05:00
2014-05-22 22:49:37 -04:00
scroll . add ( this . _extensionSelector ) ;
2012-01-18 21:21:56 -05:00
2018-08-05 20:31:18 -04:00
this . _mainStack . add _named ( scroll , 'listing' ) ;
this . _mainStack . add _named ( new EmptyPlaceholder ( ) , 'placeholder' ) ;
2012-01-18 21:21:56 -05:00
this . _shellProxy = new GnomeShellProxy ( Gio . DBus . session , 'org.gnome.Shell' , '/org/gnome/Shell' ) ;
2017-10-30 20:38:18 -04:00
this . _shellProxy . connectSignal ( 'ExtensionStatusChanged' , ( proxy , senderName , [ uuid , state , error ] ) => {
2012-01-30 20:58:29 -05:00
if ( ExtensionUtils . extensions [ uuid ] !== undefined )
2012-01-18 21:21:56 -05:00
this . _scanExtensions ( ) ;
2017-10-30 20:38:18 -04:00
} ) ;
2012-01-18 21:21:56 -05:00
this . _window . show _all ( ) ;
2017-10-30 21:19:44 -04:00
}
2012-01-18 21:21:56 -05:00
2017-10-30 20:03:21 -04:00
_sortList ( row1 , row2 ) {
2014-05-22 22:49:37 -04:00
let name1 = ExtensionUtils . extensions [ row1 . uuid ] . metadata . name ;
let name2 = ExtensionUtils . extensions [ row2 . uuid ] . metadata . name ;
return name1 . localeCompare ( name2 ) ;
2017-10-30 21:19:44 -04:00
}
2014-05-22 22:49:37 -04:00
2017-10-30 20:03:21 -04:00
_updateHeader ( row , before ) {
2014-05-22 22:49:37 -04:00
if ( ! before || row . get _header ( ) )
return ;
let sep = new Gtk . Separator ( { orientation : Gtk . Orientation . HORIZONTAL } ) ;
row . set _header ( sep ) ;
2017-10-30 21:19:44 -04:00
}
2014-05-22 22:49:37 -04:00
2017-10-30 20:03:21 -04:00
_scanExtensions ( ) {
2012-06-04 17:14:18 -04:00
let finder = new ExtensionUtils . ExtensionFinder ( ) ;
2017-12-01 19:27:35 -05:00
finder . connect ( 'extension-found' , this . _extensionFound . bind ( this ) ) ;
2012-06-04 17:14:18 -04:00
finder . scanExtensions ( ) ;
2013-11-04 10:07:44 -05:00
this . _extensionsLoaded ( ) ;
2017-10-30 21:19:44 -04:00
}
2012-01-18 21:21:56 -05:00
2017-10-30 20:03:21 -04:00
_extensionFound ( finder , extension ) {
2014-05-22 22:49:37 -04:00
let row = new ExtensionRow ( extension . uuid ) ;
row . prefsButton . visible = this . _extensionAvailable ( row . uuid ) ;
2017-10-30 20:38:18 -04:00
row . prefsButton . connect ( 'clicked' , ( ) => {
this . _selectExtension ( row . uuid ) ;
} ) ;
2014-05-22 22:49:37 -04:00
row . show _all ( ) ;
this . _extensionSelector . add ( row ) ;
2017-10-30 21:19:44 -04:00
}
2012-06-04 17:14:18 -04:00
2017-10-30 20:03:21 -04:00
_extensionsLoaded ( ) {
2018-08-05 20:31:18 -04:00
if ( this . _extensionSelector . get _children ( ) . length > 0 )
this . _mainStack . visible _child _name = 'listing' ;
else
this . _mainStack . visible _child _name = 'placeholder' ;
2013-02-28 08:50:56 -05:00
if ( this . _startupUuid && this . _extensionAvailable ( this . _startupUuid ) )
this . _selectExtension ( this . _startupUuid ) ;
this . _startupUuid = null ;
2014-05-26 19:36:41 -04:00
this . _skipMainWindow = false ;
this . _loaded = true ;
2017-10-30 21:19:44 -04:00
}
2012-06-04 17:14:18 -04:00
2017-10-30 20:03:21 -04:00
_onActivate ( ) {
2012-01-18 21:21:56 -05:00
this . _window . present ( ) ;
2017-10-30 21:19:44 -04:00
}
2012-01-18 21:21:56 -05:00
2017-10-30 20:03:21 -04:00
_onStartup ( app ) {
2012-01-18 21:21:56 -05:00
this . _buildUI ( app ) ;
this . _scanExtensions ( ) ;
2017-10-30 21:19:44 -04:00
}
2012-01-18 21:21:56 -05:00
2017-10-30 20:03:21 -04:00
_onCommandLine ( app , commandLine ) {
2012-01-18 21:21:56 -05:00
app . activate ( ) ;
let args = commandLine . get _arguments ( ) ;
2014-05-26 19:36:41 -04:00
2012-01-18 21:21:56 -05:00
if ( args . length ) {
let uuid = args [ 0 ] ;
2014-05-26 19:36:41 -04:00
this . _skipMainWindow = true ;
2012-01-18 21:21:56 -05:00
// Strip off "extension:///" prefix which fakes a URI, if it exists
uuid = stripPrefix ( uuid , "extension:///" ) ;
2013-02-28 08:50:56 -05:00
if ( this . _extensionAvailable ( uuid ) )
this . _selectExtension ( uuid ) ;
2014-05-26 19:36:41 -04:00
else if ( ! this . _loaded )
2013-02-28 08:50:56 -05:00
this . _startupUuid = uuid ;
2014-05-26 19:36:41 -04:00
else
this . _skipMainWindow = false ;
2012-01-18 21:21:56 -05:00
}
return 0 ;
}
2017-10-30 21:19:44 -04:00
} ;
2012-01-18 21:21:56 -05:00
2018-08-05 22:15:12 -04:00
var Expander = GObject . registerClass ( {
Properties : {
'label' : GObject . ParamSpec . string (
'label' , 'label' , 'label' ,
GObject . ParamFlags . READWRITE ,
null
)
}
} , class Expander extends Gtk . Box {
_init ( params = { } ) {
this . _labelText = null ;
super . _init ( Object . assign ( params , {
orientation : Gtk . Orientation . VERTICAL ,
spacing : 0
} ) ) ;
this . _frame = new Gtk . Frame ( {
shadow _type : Gtk . ShadowType . IN ,
hexpand : true
} ) ;
let eventBox = new Gtk . EventBox ( ) ;
this . _frame . add ( eventBox ) ;
let hbox = new Gtk . Box ( {
spacing : 6 ,
margin : 12
} ) ;
eventBox . add ( hbox ) ;
this . _arrow = new Gtk . Image ( {
icon _name : 'pan-end-symbolic'
} ) ;
hbox . add ( this . _arrow ) ;
this . _label = new Gtk . Label ( { label : this . _labelText } ) ;
hbox . add ( this . _label ) ;
this . _revealer = new Gtk . Revealer ( ) ;
this . _childBin = new Gtk . Frame ( {
shadow _type : Gtk . ShadowType . IN
} ) ;
this . _revealer . add ( this . _childBin ) ;
// Directly chain up to parent for internal children
super . add ( this . _frame ) ;
super . add ( this . _revealer ) ;
let provider = new Gtk . CssProvider ( ) ;
provider . load _from _data ( '* { border-top-width: 0; }' ) ;
this . _childBin . get _style _context ( ) . add _provider (
provider ,
Gtk . STYLE _PROVIDER _PRIORITY _APPLICATION
) ;
this . _gesture = new Gtk . GestureMultiPress ( {
widget : this . _frame ,
button : 0 ,
exclusive : true
} ) ;
this . _gesture . connect ( 'released' , ( gesture , nPress ) => {
if ( nPress == 1 )
this . _revealer . reveal _child = ! this . _revealer . reveal _child ;
} ) ;
this . _revealer . connect ( 'notify::reveal-child' , ( ) => {
if ( this . _revealer . reveal _child )
this . _arrow . icon _name = 'pan-down-symbolic' ;
else
this . _arrow . icon _name = 'pan-end-symbolic' ;
} ) ;
}
get label ( ) {
return this . _labelText ;
}
set label ( text ) {
if ( this . _labelText == text )
return ;
if ( this . _label )
this . _label . label = text ;
this . _labelText = text ;
this . notify ( 'label' ) ;
}
add ( child ) {
// set expanded child
this . _childBin . get _children ( ) . forEach ( c => {
this . _childBin . remove ( c ) ;
} ) ;
if ( child )
this . _childBin . add ( child ) ;
}
} ) ;
2018-08-05 20:31:18 -04:00
var EmptyPlaceholder = GObject . registerClass (
class EmptyPlaceholder extends Gtk . Box {
_init ( ) {
super . _init ( {
orientation : Gtk . Orientation . VERTICAL ,
spacing : 6 ,
margin : 32
} ) ;
let image = new Gtk . Image ( {
icon _name : 'application-x-addon-symbolic' ,
pixel _size : 96 ,
visible : true ,
vexpand : true ,
valign : Gtk . Align . END
} ) ;
image . get _style _context ( ) . add _class ( Gtk . STYLE _CLASS _DIM _LABEL ) ;
this . add ( image ) ;
let label = new Gtk . Label ( {
label : ` <b><span size="x-large"> ${ _ ( "No Extensions Installed" ) } </span></b> ` ,
use _markup : true ,
visible : true
} ) ;
label . get _style _context ( ) . add _class ( Gtk . STYLE _CLASS _DIM _LABEL ) ;
this . add ( label ) ;
let appInfo = Gio . DesktopAppInfo . new ( 'org.gnome.Software.desktop' ) ;
let desc = new Gtk . Label ( {
label : _ ( "Extensions can be installed through Software or <a href=\"https://extensions.gnome.org\">extensions.gnome.org</a>." ) ,
use _markup : true ,
wrap : true ,
justify : Gtk . Justification . CENTER ,
visible : true ,
max _width _chars : 50 ,
hexpand : true ,
vexpand : ( appInfo == null ) ,
halign : Gtk . Align . CENTER ,
valign : Gtk . Align . START
} ) ;
this . add ( desc ) ;
if ( appInfo ) {
let button = new Gtk . Button ( {
label : _ ( "Browse in Software" ) ,
image : new Gtk . Image ( {
icon _name : "org.gnome.Software-symbolic"
} ) ,
always _show _image : true ,
margin _top : 12 ,
visible : true ,
halign : Gtk . Align . CENTER ,
valign : Gtk . Align . START ,
vexpand : true
} ) ;
this . add ( button ) ;
button . connect ( 'clicked' , w => {
let context = w . get _display ( ) . get _app _launch _context ( ) ;
appInfo . launch ( [ ] , context ) ;
} ) ;
}
}
} ) ;
2017-10-30 21:23:39 -04:00
var DescriptionLabel = GObject . registerClass (
class DescriptionLabel extends Gtk . Label {
2017-10-30 20:03:21 -04:00
vfunc _get _preferred _height _for _width ( width ) {
2015-12-14 18:37:47 -05:00
// Hack: Request the maximum height allowed by the line limit
if ( this . lines > 0 )
2017-10-30 21:23:39 -04:00
return super . vfunc _get _preferred _height _for _width ( 0 ) ;
return super . vfunc _get _preferred _height _for _width ( width ) ;
2015-12-14 18:37:47 -05:00
}
} ) ;
2017-10-30 21:23:39 -04:00
var ExtensionRow = GObject . registerClass (
class ExtensionRow extends Gtk . ListBoxRow {
2017-10-30 20:03:21 -04:00
_init ( uuid ) {
2017-10-30 21:23:39 -04:00
super . _init ( ) ;
2014-05-22 22:49:37 -04:00
this . uuid = uuid ;
2014-06-24 15:17:09 -04:00
this . _settings = new Gio . Settings ( { schema _id : 'org.gnome.shell' } ) ;
2017-10-30 20:38:18 -04:00
this . _settings . connect ( 'changed::enabled-extensions' , ( ) => {
this . _switch . state = this . _isEnabled ( ) ;
} ) ;
2014-09-06 09:27:52 -04:00
this . _settings . connect ( 'changed::disable-extension-version-validation' ,
2017-10-30 20:38:18 -04:00
( ) => {
2014-09-06 09:27:52 -04:00
this . _switch . sensitive = this . _canEnable ( ) ;
2017-10-30 20:38:18 -04:00
} ) ;
2015-12-14 18:15:33 -05:00
this . _settings . connect ( 'changed::disable-user-extensions' ,
2017-10-30 20:38:18 -04:00
( ) => {
2015-12-14 18:15:33 -05:00
this . _switch . sensitive = this . _canEnable ( ) ;
2017-10-30 20:38:18 -04:00
} ) ;
2014-05-26 17:40:26 -04:00
2014-05-22 22:49:37 -04:00
this . _buildUI ( ) ;
2017-10-30 21:23:39 -04:00
}
2014-05-22 22:49:37 -04:00
2017-10-30 20:03:21 -04:00
_buildUI ( ) {
2014-05-22 22:49:37 -04:00
let extension = ExtensionUtils . extensions [ this . uuid ] ;
let hbox = new Gtk . Box ( { orientation : Gtk . Orientation . HORIZONTAL ,
2015-12-14 18:37:47 -05:00
hexpand : true , margin _end : 24 , spacing : 24 ,
margin : 12 } ) ;
2014-05-22 22:49:37 -04:00
this . add ( hbox ) ;
let vbox = new Gtk . Box ( { orientation : Gtk . Orientation . VERTICAL ,
spacing : 6 , hexpand : true } ) ;
hbox . add ( vbox ) ;
let name = GLib . markup _escape _text ( extension . metadata . name , - 1 ) ;
let label = new Gtk . Label ( { label : '<b>' + name + '</b>' ,
use _markup : true ,
halign : Gtk . Align . START } ) ;
vbox . add ( label ) ;
let desc = extension . metadata . description . split ( '\n' ) [ 0 ] ;
2015-12-14 18:37:47 -05:00
label = new DescriptionLabel ( { label : desc , wrap : true , lines : 2 ,
ellipsize : Pango . EllipsizeMode . END ,
xalign : 0 , yalign : 0 } ) ;
2014-05-22 22:49:37 -04:00
vbox . add ( label ) ;
let button = new Gtk . Button ( { valign : Gtk . Align . CENTER ,
no _show _all : true } ) ;
2019-04-05 12:24:09 -04:00
button . set _image ( new Gtk . Image ( { icon _name : 'emblem-system-symbolic' ,
icon _size : Gtk . IconSize . BUTTON ,
visible : true } ) ) ;
2016-03-03 18:48:02 -05:00
button . get _style _context ( ) . add _class ( 'circular' ) ;
2014-05-22 22:49:37 -04:00
hbox . add ( button ) ;
this . prefsButton = button ;
2014-05-26 17:40:26 -04:00
this . _switch = new Gtk . Switch ( { valign : Gtk . Align . CENTER ,
2014-09-06 09:27:52 -04:00
sensitive : this . _canEnable ( ) ,
2014-05-26 17:40:26 -04:00
state : this . _isEnabled ( ) } ) ;
2017-10-30 20:38:18 -04:00
this . _switch . connect ( 'notify::active' , ( ) => {
if ( this . _switch . active )
this . _enable ( ) ;
else
this . _disable ( ) ;
} ) ;
this . _switch . connect ( 'state-set' , ( ) => true ) ;
2014-05-26 17:40:26 -04:00
hbox . add ( this . _switch ) ;
2017-10-30 21:23:39 -04:00
}
2014-05-26 17:40:26 -04:00
2017-10-30 20:03:21 -04:00
_canEnable ( ) {
2014-09-06 09:27:52 -04:00
let extension = ExtensionUtils . extensions [ this . uuid ] ;
let checkVersion = ! this . _settings . get _boolean ( 'disable-extension-version-validation' ) ;
2015-12-14 18:15:33 -05:00
return ! this . _settings . get _boolean ( 'disable-user-extensions' ) &&
! ( checkVersion && ExtensionUtils . isOutOfDate ( extension ) ) ;
2017-10-30 21:23:39 -04:00
}
2014-09-06 09:27:52 -04:00
2017-10-30 20:03:21 -04:00
_isEnabled ( ) {
2014-05-26 17:40:26 -04:00
let extensions = this . _settings . get _strv ( 'enabled-extensions' ) ;
2018-07-14 16:56:22 -04:00
return extensions . includes ( this . uuid ) ;
2017-10-30 21:23:39 -04:00
}
2014-05-26 17:40:26 -04:00
2017-10-30 20:03:21 -04:00
_enable ( ) {
2014-05-26 17:40:26 -04:00
let extensions = this . _settings . get _strv ( 'enabled-extensions' ) ;
2018-07-14 16:56:22 -04:00
if ( extensions . includes ( this . uuid ) )
2014-05-26 17:40:26 -04:00
return ;
extensions . push ( this . uuid ) ;
this . _settings . set _strv ( 'enabled-extensions' , extensions ) ;
2017-10-30 21:23:39 -04:00
}
2014-05-26 17:40:26 -04:00
2017-10-30 20:03:21 -04:00
_disable ( ) {
2014-05-26 17:40:26 -04:00
let extensions = this . _settings . get _strv ( 'enabled-extensions' ) ;
let pos = extensions . indexOf ( this . uuid ) ;
if ( pos == - 1 )
return ;
do {
extensions . splice ( pos , 1 ) ;
pos = extensions . indexOf ( this . uuid ) ;
} while ( pos != - 1 ) ;
this . _settings . set _strv ( 'enabled-extensions' , extensions ) ;
2014-05-22 22:49:37 -04:00
}
} ) ;
2012-01-18 21:21:56 -05:00
function initEnvironment ( ) {
// Monkey-patch in a "global" object that fakes some Shell utilities
// that ExtensionUtils depends on.
window . global = {
2019-02-12 06:24:30 -05:00
log ( ... args ) {
print ( args . join ( ', ' ) ) ;
2012-01-18 21:21:56 -05:00
} ,
2017-10-30 20:03:21 -04:00
logError ( s ) {
2019-01-29 19:18:24 -05:00
log ( ` ERROR: ${ s } ` ) ;
2012-01-18 21:21:56 -05:00
} ,
userdatadir : GLib . build _filenamev ( [ GLib . get _user _data _dir ( ) , 'gnome-shell' ] )
} ;
String . prototype . format = Format . format ;
}
function main ( argv ) {
initEnvironment ( ) ;
Gettext . bindtextdomain ( Config . GETTEXT _PACKAGE , Config . LOCALEDIR ) ;
Gettext . textdomain ( Config . GETTEXT _PACKAGE ) ;
let app = new Application ( ) ;
app . application . run ( argv ) ;
}