2 * Copyright 2013,2015 Canonical Ltd.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; version 3.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18import Ubuntu.Settings.Menus 0.1 as Menus
19import Ubuntu.Settings.Components 0.1
21import Utils 0.1 as Utils
22import Ubuntu.Components.ListItems 0.1 as ListItems
23import Ubuntu.Components 1.2
24import Unity.Session 0.1
29 property var rootModel: null
30 property var menuModel: null
34 "unity.widgets.systemsettings.tablet.volumecontrol" : sliderMenu,
35 "unity.widgets.systemsettings.tablet.switch" : switchMenu,
37 "com.canonical.indicator.button" : buttonMenu,
38 "com.canonical.indicator.div" : separatorMenu,
39 "com.canonical.indicator.section" : sectionMenu,
40 "com.canonical.indicator.progress" : progressMenu,
41 "com.canonical.indicator.slider" : sliderMenu,
42 "com.canonical.indicator.switch" : switchMenu,
43 "com.canonical.indicator.alarm" : alarmMenu,
44 "com.canonical.indicator.appointment" : appointmentMenu,
45 "com.canonical.indicator.transfer" : transferMenu,
46 "com.canonical.indicator.button-section" : buttonSectionMenu,
47 "com.canonical.indicator.link" : linkMenu,
49 "com.canonical.indicator.messages.messageitem" : messageItem,
50 "com.canonical.indicator.messages.sourceitem" : groupedMessage,
52 "com.canonical.unity.slider" : sliderMenu,
53 "com.canonical.unity.switch" : switchMenu,
55 "com.canonical.unity.media-player" : mediaPayerMenu,
56 "com.canonical.unity.playback-item" : playbackItemMenu,
58 "unity.widgets.systemsettings.tablet.wifisection" : wifiSection,
59 "unity.widgets.systemsettings.tablet.accesspoint" : accessPoint,
60 "com.canonical.indicator.network.modeminfoitem" : modeminfoitem,
62 "com.canonical.indicator.calendar": calendarMenu,
63 "com.canonical.indicator.location": timezoneMenu,
65 "indicator.user-menu-item": userMenuItem,
66 "indicator.guest-menu-item": userMenuItem
68 "indicator-messages" : {
69 "com.canonical.indicator.button" : messagesButtonMenu
73 function getExtendedProperty(object, propertyName, defaultValue) {
74 if (object && object.hasOwnProperty(propertyName)) {
75 return object[propertyName];
84 objectName: "separatorMenu"
93 objectName: "sliderMenu"
94 property QtObject menuData: null
95 property var menuModel: menuFactory.menuModel
96 property int menuIndex: -1
97 property var extendedData: menuData && menuData.ext || undefined
98 property var serverValue: getExtendedProperty(menuData, "actionState", undefined)
100 text: menuData && menuData.label || ""
101 iconSource: menuData && menuData.icon || ""
102 minIcon: getExtendedProperty(extendedData, "minIcon", "")
103 maxIcon: getExtendedProperty(extendedData, "maxIcon", "")
105 minimumValue: getExtendedProperty(extendedData, "minValue", 0.0)
107 var maximum = getExtendedProperty(extendedData, "maxValue", 1.0);
108 if (maximum <= minimumValue) {
109 return minimumValue + 1;
113 enabled: menuData && menuData.sensitive || false
114 highlightWhenPressed: false
116 onMenuModelChanged: {
119 onMenuIndexChanged: {
123 function loadAttributes() {
124 if (!menuModel || menuIndex == -1) return;
125 menuModel.loadExtendedAttributes(menuIndex, {'min-value': 'double',
126 'max-value': 'double',
128 'max-icon': 'icon'});
131 ServerPropertySynchroniser {
133 syncTimeout: Utils.Constants.indicatorValueTimeout
134 bufferedSyncTimeout: true
135 maximumWaitBufferInterval: 16
137 serverTarget: sliderItem
138 serverProperty: "serverValue"
139 userTarget: sliderItem
140 userProperty: "value"
142 onSyncTriggered: menuModel.changeState(menuIndex, value)
151 objectName: "buttonMenu"
152 property QtObject menuData: null
153 property var menuModel: menuFactory.menuModel
154 property int menuIndex: -1
156 buttonText: menuData && menuData.label || ""
157 enabled: menuData && menuData.sensitive || false
158 highlightWhenPressed: false
161 menuModel.activate(menuIndex);
167 id: messagesButtonMenu;
170 objectName: "messagesButtonMenu"
171 property QtObject menuData: null
172 property var menuModel: menuFactory.menuModel
173 property int menuIndex: -1
175 implicitHeight: units.gu(5)
176 enabled: menuData && menuData.sensitive || false
180 text: menuData && menuData.label || ""
181 anchors.centerIn: parent
187 fill: buttonMenuLabel
188 margins: units.gu(-1)
190 onClicked: menuModel.activate(menuIndex);
199 objectName: "sectionMenu"
200 property QtObject menuData: null
201 property var menuIndex: undefined
203 text: menuData && menuData.label || ""
211 Menus.ProgressValueMenu {
212 objectName: "progressMenu"
213 property QtObject menuData: null
214 property int menuIndex: -1
216 text: menuData && menuData.label || ""
217 iconSource: menuData && menuData.icon || ""
218 value : menuData && menuData.actionState || 0.0
219 enabled: menuData && menuData.sensitive || false
220 highlightWhenPressed: false
228 objectName: "standardMenu"
229 property QtObject menuData: null
230 property int menuIndex: -1
232 text: menuData && menuData.label || ""
233 iconSource: menuData && menuData.icon || ""
234 enabled: menuData && menuData.sensitive || false
235 highlightWhenPressed: false
238 menuModel.activate(menuIndex);
241 // FIXME : At the moment, the indicators aren't using
242 // com.canonical.indicators.link for settings menu. Need to fudge it.
243 property bool settingsMenu: menuData && menuData.action.indexOf("settings") > -1 || false
244 backColor: settingsMenu ? Qt.rgba(1,1,1,0.07) : "transparent"
245 component: settingsMenu ? buttonForSettings : undefined
247 id: buttonForSettings
252 color: Theme.palette.selected.backgroundText
262 objectName: "linkMenu"
263 property QtObject menuData: null
264 property int menuIndex: -1
266 text: menuData && menuData.label || ""
267 iconSource: menuData && menuData.icon || ""
268 enabled: menuData && menuData.sensitive || false
269 highlightWhenPressed: false
272 menuModel.activate(menuIndex);
275 backColor: Qt.rgba(1,1,1,0.07)
277 component: menuData.icon ? icon : undefined
281 source: menuData.icon
284 color: Theme.palette.selected.backgroundText
293 Menus.CheckableMenu {
295 objectName: "checkableMenu"
296 property QtObject menuData: null
297 property int menuIndex: -1
298 property bool serverChecked: menuData && menuData.isToggled || false
300 text: menuData && menuData.label || ""
301 enabled: menuData && menuData.sensitive || false
302 checked: serverChecked
303 highlightWhenPressed: false
305 ServerPropertySynchroniser {
307 syncTimeout: Utils.Constants.indicatorValueTimeout
309 serverTarget: checkItem
310 serverProperty: "serverChecked"
311 userTarget: checkItem
312 userProperty: "checked"
314 onSyncTriggered: menuModel.activate(checkItem.menuIndex)
324 objectName: "switchMenu"
325 property QtObject menuData: null
326 property int menuIndex: -1
327 property bool serverChecked: menuData && menuData.isToggled || false
329 text: menuData && menuData.label || ""
330 iconSource: menuData && menuData.icon || ""
331 enabled: menuData && menuData.sensitive || false
332 checked: serverChecked
333 highlightWhenPressed: false
335 ServerPropertySynchroniser {
337 syncTimeout: Utils.Constants.indicatorValueTimeout
339 serverTarget: switchItem
340 serverProperty: "serverChecked"
341 userTarget: switchItem
342 userProperty: "checked"
344 onSyncTriggered: menuModel.activate(switchItem.menuIndex);
353 objectName: "alarmMenu"
354 property QtObject menuData: null
355 property var menuModel: menuFactory.menuModel
356 property int menuIndex: -1
357 property var extendedData: menuData && menuData.ext || undefined
358 // TODO - bug #1260728
359 property var timeFormatter: Utils.GDateTimeFormatter {
360 time: getExtendedProperty(extendedData, "xCanonicalTime", 0)
361 format: getExtendedProperty(extendedData, "xCanonicalTimeFormat", "")
364 text: menuData && menuData.label || ""
365 iconSource: menuData && menuData.icon || "image://theme/alarm-clock"
366 time: timeFormatter.timeString
367 enabled: menuData && menuData.sensitive || false
368 highlightWhenPressed: false
370 onMenuModelChanged: {
373 onMenuIndexChanged: {
377 menuModel.activate(menuIndex);
380 function loadAttributes() {
381 if (!menuModel || menuIndex == -1) return;
382 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-time': 'int64',
383 'x-canonical-time-format': 'string'});
392 objectName: "appointmentMenu"
393 property QtObject menuData: null
394 property var menuModel: menuFactory.menuModel
395 property int menuIndex: -1
396 property var extendedData: menuData && menuData.ext || undefined
397 // TODO - bug #1260728
398 property var timeFormatter: Utils.GDateTimeFormatter {
399 time: getExtendedProperty(extendedData, "xCanonicalTime", 0)
400 format: getExtendedProperty(extendedData, "xCanonicalTimeFormat", "")
403 text: menuData && menuData.label || ""
404 iconSource: menuData && menuData.icon || "image://theme/calendar"
405 time: timeFormatter.timeString
406 eventColor: getExtendedProperty(extendedData, "xCanonicalColor", Qt.rgba(0.0, 0.0, 0.0, 0.0))
407 enabled: menuData && menuData.sensitive || false
408 highlightWhenPressed: false
410 onMenuModelChanged: {
413 onMenuIndexChanged: {
417 menuModel.activate(menuIndex);
420 function loadAttributes() {
421 if (!menuModel || menuIndex == -1) return;
422 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-color': 'string',
423 'x-canonical-time': 'int64',
424 'x-canonical-time-format': 'string'});
432 Menus.UserSessionMenu {
433 objectName: "userSessionMenu"
434 highlightWhenPressed: false
436 property QtObject menuData: null
437 property var menuModel: menuFactory.menuModel
438 property int menuIndex: -1
440 name: menuData && menuData.label || "" // label is the user's real name
441 iconSource: menuData && menuData.icon || ""
443 // would be better to compare with the logname but sadly the indicator doesn't expose that
444 active: DBusUnitySessionService.RealName() !== "" ? DBusUnitySessionService.RealName() == name
445 : DBusUnitySessionService.UserName() == name
448 menuModel.activate(menuIndex);
457 objectName: "calendarMenu"
458 highlightWhenPressed: false
468 objectName: "timezoneMenu"
470 property QtObject menuData: null
471 property var menuModel: menuFactory.menuModel
472 property int menuIndex: -1
473 property var extendedData: menuData && menuData.ext || undefined
474 readonly property string tz: getExtendedProperty(extendedData, "xCanonicalTimezone", "UTC")
475 property var updateTimer: Timer {
477 running: tzMenuItem.visible // only run when we're open
478 onTriggered: tzMenuItem.time = Utils.TimezoneFormatter.currentTimeInTimezone(tzMenuItem.tz)
481 city: menuData && menuData.label || ""
482 time: Utils.TimezoneFormatter.currentTimeInTimezone(tz)
483 enabled: menuData && menuData.sensitive || false
485 onMenuModelChanged: {
488 onMenuIndexChanged: {
492 tzActionGroup.setLocation.activate(tz);
497 busType: DBus.SessionBus
498 busName: "com.canonical.indicator.datetime"
499 objectPath: "/com/canonical/indicator/datetime"
501 property variant setLocation: action("set-location")
503 Component.onCompleted: tzActionGroup.start()
506 function loadAttributes() {
507 if (!menuModel || menuIndex == -1) return;
508 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-timezone': 'string'});
517 objectName: "wifiSection"
518 property QtObject menuData: null
519 property var menuModel: menuFactory.menuModel
520 property int menuIndex: -1
521 property var extendedData: menuData && menuData.ext || undefined
523 text: menuData && menuData.label || ""
524 busy: getExtendedProperty(extendedData, "xCanonicalBusyAction", false)
526 onMenuModelChanged: {
529 onMenuIndexChanged: {
533 function loadAttributes() {
534 if (!menuModel || menuIndex == -1) return;
535 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-busy-action': 'bool'})
543 Menus.AccessPointMenu {
545 objectName: "accessPoint"
546 property QtObject menuData: null
547 property var menuModel: menuFactory.menuModel
548 property int menuIndex: -1
549 property var extendedData: menuData && menuData.ext || undefined
550 property bool serverChecked: menuData && menuData.isToggled || false
552 property var strengthAction: UnityMenuAction {
555 name: getExtendedProperty(extendedData, "xCanonicalWifiApStrengthAction", "")
558 text: menuData && menuData.label || ""
559 enabled: menuData && menuData.sensitive || false
560 active: serverChecked
561 secure: getExtendedProperty(extendedData, "xCanonicalWifiApIsSecure", false)
562 adHoc: getExtendedProperty(extendedData, "xCanonicalWifiApIsAdhoc", false)
563 signalStrength: strengthAction.valid ? strengthAction.state : 0
564 highlightWhenPressed: false
566 onMenuModelChanged: {
569 onMenuIndexChanged: {
573 function loadAttributes() {
574 if (!menuModel || menuIndex == -1) return;
575 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-wifi-ap-is-adhoc': 'bool',
576 'x-canonical-wifi-ap-is-secure': 'bool',
577 'x-canonical-wifi-ap-strength-action': 'string'});
580 ServerPropertySynchroniser {
582 syncTimeout: Utils.Constants.indicatorValueTimeout
585 serverProperty: "serverChecked"
587 userProperty: "active"
588 userTrigger: "onTriggered"
590 onSyncTriggered: menuModel.activate(apItem.menuIndex)
598 objectName: "modemInfoItem"
599 property QtObject menuData: null
600 property var menuModel: menuFactory.menuModel
601 property int menuIndex: -1
602 property var extendedData: menuData && menuData.ext || undefined
603 highlightWhenPressed: false
605 property var statusLabelAction: UnityMenuAction {
608 name: getExtendedProperty(extendedData, "xCanonicalModemStatusLabelAction", "")
610 statusText: statusLabelAction.valid ? statusLabelAction.state : ""
612 property var statusIconAction: UnityMenuAction {
615 name: getExtendedProperty(extendedData, "xCanonicalModemStatusIconAction", "")
617 statusIcon: statusIconAction.valid ? statusIconAction.state : ""
619 property var connectivityIconAction: UnityMenuAction {
622 name: getExtendedProperty(extendedData, "xCanonicalModemConnectivityIconAction", "")
624 connectivityIcon: connectivityIconAction.valid ? connectivityIconAction.state : ""
626 property var simIdentifierLabelAction: UnityMenuAction {
629 name: getExtendedProperty(extendedData, "xCanonicalModemSimIdentifierLabelAction", "")
631 simIdentifierText: simIdentifierLabelAction.valid ? simIdentifierLabelAction.state : ""
633 property var roamingAction: UnityMenuAction {
636 name: getExtendedProperty(extendedData, "xCanonicalModemRoamingAction", "")
638 roaming: roamingAction.valid ? roamingAction.state : false
640 property var unlockAction: UnityMenuAction {
643 name: getExtendedProperty(extendedData, "xCanonicalModemLockedAction", "")
646 unlockAction.activate();
648 locked: unlockAction.valid ? unlockAction.state : false
650 onMenuModelChanged: {
653 onMenuIndexChanged: {
657 function loadAttributes() {
658 if (!menuModel || menuIndex == -1) return;
659 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-modem-status-label-action': 'string',
660 'x-canonical-modem-status-icon-action': 'string',
661 'x-canonical-modem-connectivity-icon-action': 'string',
662 'x-canonical-modem-sim-identifier-label-action': 'string',
663 'x-canonical-modem-roaming-action': 'string',
664 'x-canonical-modem-locked-action': 'string'});
672 MessageMenuItemFactory {
673 objectName: "messageItem"
674 menuModel: menuFactory.menuModel
681 Menus.GroupedMessageMenu {
682 objectName: "groupedMessage"
683 property QtObject menuData: null
684 property var menuModel: menuFactory.menuModel
685 property int menuIndex: -1
686 property var extendedData: menuData && menuData.ext || undefined
688 text: menuData && menuData.label || ""
689 iconSource: getExtendedProperty(extendedData, "icon", "image://theme/message")
690 count: menuData && menuData.actionState.length > 0 ? menuData.actionState[0] : "0"
691 enabled: menuData && menuData.sensitive || false
692 highlightWhenPressed: false
695 onMenuModelChanged: {
698 onMenuIndexChanged: {
702 menuModel.activate(menuIndex, true);
705 menuModel.activate(menuIndex, false);
708 function loadAttributes() {
709 if (!menuModel || menuIndex == -1) return;
710 menuModel.loadExtendedAttributes(modelIndex, {'icon': 'icon'});
718 Menus.MediaPlayerMenu {
719 objectName: "mediaPayerMenu"
720 property QtObject menuData: null
721 property var menuModel: menuFactory.menuModel
722 property int menuIndex: -1
723 property var actionState: menuData && menuData.actionState || undefined
724 property bool running: getExtendedProperty(actionState, "running", false)
726 playerIcon: menuData && menuData.icon || "image://theme/stock_music"
727 playerName: menuData && menuData.label || i18n.tr("Nothing is playing")
729 albumArt: getExtendedProperty(actionState, "art-url", "image://theme/stock_music")
730 song: getExtendedProperty(actionState, "title", "")
731 artist: getExtendedProperty(actionState, "artist", "")
732 album: getExtendedProperty(actionState, "album", "")
733 showTrack: running && (state == "Playing" || state == "Paused")
734 state: getExtendedProperty(actionState, "state", "")
735 enabled: menuData && menuData.sensitive || false
736 highlightWhenPressed: false
740 model.activate(modelIndex);
746 id: playbackItemMenu;
748 Menus.PlaybackItemMenu {
749 objectName: "playbackItemMenu"
750 property QtObject menuData: null
751 property var menuModel: menuFactory.menuModel
752 property int menuIndex: -1
753 property var extendedData: menuData && menuData.ext || undefined
755 property var playAction: UnityMenuAction {
758 name: getExtendedProperty(extendedData, "xCanonicalPlayAction", "")
760 property var nextAction: UnityMenuAction {
763 name: getExtendedProperty(extendedData, "xCanonicalNextAction", "")
765 property var previousAction: UnityMenuAction {
768 name: getExtendedProperty(extendedData, "xCanonicalPreviousAction", "")
771 playing: playAction.state === "Playing"
772 canPlay: playAction.valid
773 canGoNext: nextAction.valid
774 canGoPrevious: previousAction.valid
775 enabled: menuData && menuData.sensitive || false
776 highlightWhenPressed: false
779 playAction.activate();
782 nextAction.activate();
785 previousAction.activate();
787 onMenuModelChanged: {
790 onMenuIndexChanged: {
794 function loadAttributes() {
795 if (!menuModel || menuIndex == -1) return;
796 menuModel.loadExtendedAttributes(modelIndex, {'x-canonical-play-action': 'string',
797 'x-canonical-next-action': 'string',
798 'x-canonical-previous-action': 'string'});
807 objectName: "transferMenu"
809 property QtObject menuData: null
810 property var menuModel: menuFactory.menuModel
811 property int menuIndex: -1
812 property var extendedData: menuData && menuData.ext || undefined
813 property var uid: getExtendedProperty(extendedData, "xCanonicalUid", undefined)
815 text: menuData && menuData.label || ""
816 iconSource: menuData && menuData.icon || "image://theme/transfer-none"
818 enabled: menuData && menuData.sensitive || false
819 highlightWhenPressed: false
826 busName: rootModel.busName
827 objectPath: rootModel.actions["indicator"]
829 property var activateAction: action("activate-transfer")
830 property var cancelAction: action("cancel-transfer")
831 property var transferStateAction: uid !== undefined ? action("transfer-state."+uid) : null
833 Component.onCompleted: actionGroup.start()
836 property var transferState: {
837 if (actionGroup.transferStateAction === null) return undefined;
838 return actionGroup.transferStateAction.valid ? actionGroup.transferStateAction.state : undefined
841 property var runningState : transferState !== undefined ? transferState["state"] : undefined
842 property var secondsLeft : transferState !== undefined ? transferState["seconds-left"] : undefined
844 active: runningState !== undefined && runningState !== Menus.TransferState.Finished
845 progress: transferState !== undefined ? transferState["percent"] : 0.0
847 // TODO - Should be in the SDK
848 property var timeRemaining: {
849 if (secondsLeft === undefined) return undefined;
852 var hours = Math.floor(secondsLeft / (60 * 60));
853 var minutes = Math.floor(secondsLeft / 60) % 60;
854 var seconds = secondsLeft % 60;
856 remaining += i18n.tr("%1 hour", "%1 hours", hours).arg(hours)
859 if (remaining != "") remaining += ", ";
860 remaining += i18n.tr("%1 minute", "%1 minutes", minutes).arg(minutes)
862 // don't include seconds if hours > 0
863 if (hours == 0 && minutes < 5 && seconds > 0) {
864 if (remaining != "") remaining += ", ";
865 remaining += i18n.tr("%1 second", "%1 seconds", seconds).arg(seconds)
868 remaining = i18n.tr("0 seconds");
869 // Translators: String like "1 hour, 2 minutes, 3 seconds remaining"
870 return i18n.tr("%1 remaining").arg(remaining);
874 switch (runningState) {
875 case Menus.TransferState.Queued:
876 return i18n.tr("In queue…");
877 case Menus.TransferState.Hashing:
878 case Menus.TransferState.Processing:
879 case Menus.TransferState.Running:
880 return timeRemaining === undefined ? i18n.tr("Downloading") : timeRemaining;
881 case Menus.TransferState.Paused:
882 return i18n.tr("Paused, tap to resume");
883 case Menus.TransferState.Canceled:
884 return i18n.tr("Canceled");
885 case Menus.TransferState.Finished:
886 return i18n.tr("Finished");
887 case Menus.TransferState.Error:
888 return i18n.tr("Failed, tap to retry");
893 onMenuModelChanged: {
896 onMenuIndexChanged: {
900 actionGroup.activateAction.activate(uid);
903 actionGroup.cancelAction.activate(uid);
906 function loadAttributes() {
907 if (!menuModel || menuIndex == -1) return;
908 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-uid': 'string'});
914 id: buttonSectionMenu;
917 objectName: "buttonSectionMenu"
918 property QtObject menuData: null
919 property var menuModel: menuFactory.menuModel
920 property int menuIndex: -1
921 property var extendedData: menuData && menuData.ext || undefined
923 iconSource: menuData && menuData.icon || ""
924 enabled: menuData && menuData.sensitive || false
925 highlightWhenPressed: false
926 text: menuData && menuData.label || ""
927 foregroundColor: Theme.palette.normal.backgroundText
929 onMenuModelChanged: {
932 onMenuIndexChanged: {
935 function loadAttributes() {
936 if (!menuModel || menuIndex == -1) return;
937 menuModel.loadExtendedAttributes(menuIndex, {'x-canonical-extra-label': 'string'});
940 component: Component {
942 objectName: "buttonSectionMenuControl"
943 text: getExtendedProperty(extendedData, "xCanonicalExtraLabel", "")
946 menuModel.activate(menuIndex);
953 function load(modelData, context) {
954 if (modelData.type !== undefined && modelData.type !== "") {
955 var component = undefined;
957 var contextComponents = _map[context];
958 if (contextComponents !== undefined) {
959 component = contextComponents[modelData.type];
962 if (component === undefined) {
963 component = _map["default"][modelData.type];
965 if (component !== undefined) {
968 console.debug("Don't know how to make " + modelData.type + " for " + context);
970 if (modelData.isCheck || modelData.isRadio) {
971 return checkableMenu;
973 if (modelData.isSeparator) {
974 return separatorMenu;
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list