Skip to content
Merged

V4 #8

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ package: $(BUILD_DIR)
install: build
rm -rf $(INSTALL_DIR)
mkdir -p $(INSTALL_DIR)
cp -r $(BUILD_DIR)/* $(INSTALL_DIR)
cp -r $(BUILD_DIR)/${SRC_DIR}/* $(INSTALL_DIR)

clean:
rm -f $(COMPILED_SCHEMAS) $(MO_FILES)
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ Either install it:
- via EGS https://extensions.gnome.org/extension/3535/gitlab-extension/
- Or download latest release: https://github.com/cinatic/gitlab-extension/releases/latest

### Quick Start
Create a ***Profile access token*** in your profile settings https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html
and use it to create a new account entry in gitlab extension settings `Account Grid`.


## Data Source
The data is fetched from the official GitLab API https://docs.gitlab.com/ee/api/.
The API has some *limitions*, e.g. it only returns domain specific data.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ var IconButton = GObject.registerClass({}, class IconButton extends St.Button {
reactive: true,
can_focus: true,
track_hover: true,
style_class: 'icon-button ' + (style_class || ''),
style_class: 'icon-button button ' + (style_class || ''),
y_align: Clutter.ActorAlign.CENTER,
...props
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ var CommitCard = GObject.registerClass({}, class CommitCard extends St.Button {
super._init({
style_class: 'card message commit-card',
can_focus: true,
x_expand: true,
hover: true
x_expand: true
})

this.cardItem = commitItem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ var PipelineCard = GObject.registerClass({}, class PipelineCard extends St.Butto
super._init({
style_class: 'card message pipeline-card',
can_focus: true,
x_expand: true,
hover: true
x_expand: true
})

this.cardItem = pipelineItem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ var ProjectCard = GObject.registerClass({}, class ProjectCard extends St.Button
super._init({
style_class: 'card message project-card',
can_focus: true,
x_expand: true,
hover: true
x_expand: true
})

this.cardItem = projectItem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ var ProjectSelectButtons = GObject.registerClass({}, class ProjectSelectButtons
style_class: 'project-select-buttons'
})

Settings.connect('changed', (value, key) => {
this._settingsChangedId = Settings.connect('changed', (value, key) => {
if (key === 'gitlab-accounts' || key === 'selected-gitlab-account-index') {
this._sync()
}
})

this.connect('destroy', this._onDestroy.bind(this))

this._sync()
}

Expand All @@ -34,7 +36,7 @@ var ProjectSelectButtons = GObject.registerClass({}, class ProjectSelectButtons

const gitlabAccountButton = new St.Button({
style_class: `message button ${additionalStyleClasses}`,
label: gitlabAccount.name,
label: gitlabAccount.name
})

gitlabAccountButton.connect('clicked', () => {
Expand All @@ -44,4 +46,10 @@ var ProjectSelectButtons = GObject.registerClass({}, class ProjectSelectButtons
this.add_child(gitlabAccountButton)
})
}

_onDestroy () {
if (this._settingsChangedId) {
Settings.disconnect(this._settingsChangedId)
}
}
})
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { Clutter, GObject, St } = imports.gi
const { GObject, St } = imports.gi

const ExtensionUtils = imports.misc.extensionUtils
const Me = ExtensionUtils.getCurrentExtension()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,31 @@ const { FlatList } = Me.imports.components.flatList.flatList
const { ProjectSelectButtons } = Me.imports.components.gitlab.projectSelectButtons
const { ProjectCard } = Me.imports.components.cards.projectCard
const { SearchBar } = Me.imports.components.searchBar.searchBar
const { Settings } = Me.imports.helpers.settings

const {
Settings,
GITLAB_ACCOUNTS,
SELECTED_GITLAB_ACCOUNT_INDEX
} = Me.imports.helpers.settings

const { Translations } = Me.imports.helpers.translations

const GitLabService = Me.imports.services.gitlab

const SETTINGS_KEYS_TO_REFRESH = [
GITLAB_ACCOUNTS,
SELECTED_GITLAB_ACCOUNT_INDEX
]

var ProjectsScreen = GObject.registerClass({}, class ProjectsScreen extends St.BoxLayout {
_init () {
super._init({
style_class: 'screen projects-screen',
vertical: true
})

this._settingsChangedId = null

const searchBar = new SearchBar()
this._list = new FlatList()

Expand All @@ -39,8 +52,8 @@ var ProjectsScreen = GObject.registerClass({}, class ProjectsScreen extends St.B

searchBar.connect('text-change', (sender, searchText) => this._filter_results(searchText))

Settings.connect('changed', (value, key) => {
if (key === 'gitlab-accounts' || key === 'selected-gitlab-account-index') {
this._settingsChangedId = Settings.connect('changed', (value, key) => {
if (SETTINGS_KEYS_TO_REFRESH.includes(key)) {
this._loadData()
}

Expand All @@ -54,6 +67,8 @@ var ProjectsScreen = GObject.registerClass({}, class ProjectsScreen extends St.B
}
}))

this.connect('destroy', this._onDestroy.bind(this))

this._loadData()
}

Expand Down Expand Up @@ -108,4 +123,10 @@ var ProjectsScreen = GObject.registerClass({}, class ProjectsScreen extends St.B
this._list.addItem(new ProjectCard(project, latestPipeline))
})
}

_onDestroy () {
if (this._settingsChangedId) {
Settings.disconnect(this._settingsChangedId)
}
}
})
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ var SearchBar = GObject.registerClass({
}

_createButtonBox () {
let buttonBox = new St.BoxLayout({
const buttonBox = new St.BoxLayout({
style_class: 'button-box',
x_align: St.Align.END
})
Expand Down
18 changes: 8 additions & 10 deletions gitlab-extension@infinicode.de/extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ var GitLabPanelMenuButton = GObject.registerClass(
super._init(0.5)

this._currentPanelPosition = null
this._settingsChangedId = null

const panelMenuIcon = new St.Icon({
gicon: ComponentsHelper.getCustomIconPath('gitlab-symbolic'),
Expand All @@ -71,11 +72,11 @@ var GitLabPanelMenuButton = GObject.registerClass(
this._screenWrapper = new ScreenWrapper()
bin.add_actor(this._screenWrapper)

Settings.connect('changed', () => this._sync())
this._settingsChangedId = Settings.connect('changed', () => this._sync())
this.menu.connect('destroy', this._destroyExtension.bind(this))
EventHandler.connect('hide-panel', () => this.menu.close())

this._sync()

EventHandler.connect('hide-panel', () => this.menu.close())
}

_sync () {
Expand Down Expand Up @@ -122,12 +123,10 @@ var GitLabPanelMenuButton = GObject.registerClass(
this._currentPanelPosition = newPosition
}

stop () {
// TODO:
// clear cache (add cache before ^^)
// ensure if destroy signal is bubbled correctly
// - unregister signal connections
// - dispose components
_destroyExtension () {
if (this._settingsChangedId) {
Settings.disconnect(this._settingsChangedId)
}
}
}
)
Expand All @@ -144,6 +143,5 @@ function enable () {
}

function disable () {
gitlabPanelMenuButton.stop()
gitlabPanelMenuButton.destroy()
}
3 changes: 2 additions & 1 deletion gitlab-extension@infinicode.de/helpers/data.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const ByteArray = imports.byteArray;
const { GLib } = imports.gi

let CACHE = {}
Expand All @@ -14,7 +15,7 @@ var fallbackIfNaN = value => typeof value === 'undefined' || value === null || i

var decodeBase64JsonOrDefault = (encodedJson, defaultValue) => {
try {
const value = JSON.parse(GLib.base64_decode(encodedJson))
const value = JSON.parse(ByteArray.toString(GLib.base64_decode(encodedJson)))

if (!value) {
return defaultValue
Expand Down
25 changes: 16 additions & 9 deletions gitlab-extension@infinicode.de/helpers/fetch.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
const Soup = imports.gi.Soup

const _httpSession = new Soup.SessionAsync({
user_agent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
timeout: 10
})
const DEFAULT_TIME_OUT_IN_SECONDS = 10
const DEFAULT_CHROME_USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'

const Response = class {
constructor (message) {
Expand All @@ -20,15 +18,19 @@ const Response = class {
}

blob () {
return this.message.response_body.data
return this.message?.response_body?.data
}

text () {
return this.message.response_body.data.toString()
return this.message.response_body?.data?.toString()
}

json () {
return JSON.parse(this.text())
try {
return JSON.parse(this.text())
} catch (e) {
return null
}
}
}

Expand All @@ -46,7 +48,7 @@ const generateQueryString = params => {
const paramKeyValues = Object.keys(params).filter(paramName => params[paramName]).map(paramName => {
let paramValue = params[paramName]

if(typeof paramValue === 'boolean'){
if (typeof paramValue === 'boolean') {
paramValue = paramValue ? 1 : 0
}

Expand All @@ -66,7 +68,12 @@ var fetch = ({ url, method = 'GET', headers, queryParameters }) => {
appendHeaders(request_message, headers)
}

_httpSession.queue_message(request_message, (source, response_message) => {
const httpSession = new Soup.SessionAsync({
user_agent: DEFAULT_CHROME_USER_AGENT,
timeout: DEFAULT_TIME_OUT_IN_SECONDS
})

httpSession.queue_message(request_message, (source, response_message) => {
const response = new Response(response_message)

resolve(response)
Expand Down
63 changes: 52 additions & 11 deletions gitlab-extension@infinicode.de/helpers/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const { GLib, Gio } = imports.gi
const ExtensionUtils = imports.misc.extensionUtils
const Me = ExtensionUtils.getCurrentExtension()

const { decodeBase64JsonOrDefault, isNullOrEmpty } = Me.imports.helpers.data
const { decodeBase64JsonOrDefault, isNullOrEmpty, isNullOrUndefined } = Me.imports.helpers.data

const POSITION_IN_PANEL_KEY = 'position-in-panel'
const GITLAB_TOKEN = 'gitlab-token'
Expand All @@ -14,7 +14,8 @@ var SETTINGS_SCHEMA_DOMAIN = 'org.gnome.shell.extensions.gitlab'

var DEFAULT_GITLAB_DATA = {
name: 'gitlab.com',
apiEndpoint: 'https://gitlab.com/api/v4'
apiEndpoint: 'https://gitlab.com/api/v4',
onlyOwnedProjects: false
}

/**
Expand Down Expand Up @@ -87,6 +88,35 @@ const Handler = class {
}

get gitlab_accounts () {
const accounts = this._loadAndValidateAccounts()

return accounts
}

set gitlab_accounts (v) {
this._settings.set_string(GITLAB_ACCOUNTS, GLib.base64_encode(JSON.stringify(v)))
}

connect (identifier, onChange) {
return this._settings.connect(identifier, onChange)
}

disconnect (connectId) {
this._settings.disconnect(connectId)
}

_loadAndValidateAccounts () {
let accounts = this._migrateAccountsFromSingleAccountStructure()

if (isNullOrEmpty(accounts)) {
const rawString = this._settings.get_string(GITLAB_ACCOUNTS)
accounts = decodeBase64JsonOrDefault(rawString, [])
}

return this._ensureHealthyGitlabAccountStructure(accounts)
}

_migrateAccountsFromSingleAccountStructure () {
/****
* For backwards compatiblity intercept here and check if old token exist
* if we found old format convert to new format and save
Expand All @@ -95,10 +125,11 @@ const Handler = class {
const oldToken = this._settings.get_string(GITLAB_TOKEN)

if (oldToken) {
const newData = [{
...DEFAULT_GITLAB_DATA,
token: oldToken
}]
const newData = [
{
...DEFAULT_GITLAB_DATA,
token: oldToken
}]

this._settings.set_string(GITLAB_TOKEN, '')
this._settings.set_string(GITLAB_ACCOUNTS, GLib.base64_encode(JSON.stringify(newData)))
Expand All @@ -108,13 +139,23 @@ const Handler = class {
} catch (e) {
log(`failed to convert old token ${e}`)
}

const rawString = this._settings.get_string(GITLAB_ACCOUNTS)
return decodeBase64JsonOrDefault(rawString, [])
}

connect (identifier, onChange) {
this._settings.connect(identifier, onChange)
_ensureHealthyGitlabAccountStructure (accounts) {
let normalizedAccounts = []

try {
normalizedAccounts = accounts.map(item => ({
name: item.name || DEFAULT_GITLAB_DATA.name,
apiEndpoint: item.apiEndpoint || DEFAULT_GITLAB_DATA.apiEndpoint,
token: item.token || '',
onlyOwnedProjects: isNullOrUndefined(item.onlyOwnedProjects) ? DEFAULT_GITLAB_DATA.onlyOwnedProjects : item.onlyOwnedProjects
}))
} catch (e) {
log(`failed to normalize accounts data ${e}`)
}

return normalizedAccounts
}
}

Expand Down
Loading