Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bundle notifications #529

Merged
merged 12 commits into from
May 13, 2023
Merged
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

## [Unreleased]

- Rebranded notifications, using our backend to find new versions of package,
and our github repository to find issues on Pulsar. Also fixed the "view issue"
and "create issue" buttons that were not working
- Bumped to latest version of `second-mate`, fixing a memory usage issue in `vscode-oniguruma`
- Removed a cache for native modules - fix bugs where an user rebuilds a native
module outside of Pulsar, but Pulsar refuses to load anyway
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
"mocha-multi-reporters": "^1.1.4",
"mock-spawn": "^0.2.6",
"normalize-package-data": "3.0.2",
"notifications": "https://codeload.github.com/atom/notifications/legacy.tar.gz/refs/tags/v0.72.1",
"notifications": "file:./packages/notifications",
"nsfw": "2.2.2",
"one-dark-syntax": "file:packages/one-dark-syntax",
"one-dark-ui": "file:packages/one-dark-ui",
Expand Down Expand Up @@ -215,7 +215,7 @@
"line-ending-selector": "file:./packages/line-ending-selector",
"link": "file:./packages/link",
"markdown-preview": "file:./packages/markdown-preview",
"notifications": "0.72.1",
"notifications": "file:./packages/notifications",
"open-on-github": "file:./packages/open-on-github",
"package-generator": "file:./packages/package-generator",
"settings-view": "file:./packages/settings-view",
Expand Down
1 change: 1 addition & 0 deletions packages/notifications/.coffeelintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
spec/fixtures
3 changes: 3 additions & 0 deletions packages/notifications/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.DS_Store
npm-debug.log
node_modules
20 changes: 20 additions & 0 deletions packages/notifications/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Copyright (c) 2014 GitHub Inc.

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 changes: 28 additions & 0 deletions packages/notifications/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
### Requirements

* Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion.
* All new code requires tests to ensure against regressions

### Description of the Change

<!--

We must be able to understand the design of your change from this description. If we can't get a good idea of what the code will be doing from the description here, the pull request may be closed at the maintainers' discretion. Keep in mind that the maintainer reviewing this PR may not be familiar with or have worked with the code here recently, so please walk us through the concepts.

-->

### Alternate Designs

<!-- Explain what other alternates were considered and why the proposed version was selected -->

### Benefits

<!-- What benefits will be realized by the code change? -->

### Possible Drawbacks

<!-- What are the possible side-effects or negative impacts of the code change? -->

### Applicable Issues

<!-- Enter any applicable Issues here -->
8 changes: 8 additions & 0 deletions packages/notifications/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Notifications package

![notifications](https://cloud.githubusercontent.com/assets/69169/5176406/350d0e80-73fd-11e4-8101-1776b9d6d8bf.gif)

### Docs

Notifications are available for use in your Pulsar packages via the `atom.notifications` `NotificationManager` object. See
https://atom.io/docs/api/latest/NotificationManager and https://atom.io/docs/api/latest/Notification for documentation.
11 changes: 11 additions & 0 deletions packages/notifications/keymaps/messages.cson
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Keybindings require three things to be fully defined: A selector that is
# matched against the focused element, the keystroke and the command to
# execute.
#
# Below is a basic keybinding which registers on all platforms by applying to
# the root workspace element.

# For more detailed documentation see
# https://atom.io/docs/latest/advanced/keymaps
'atom-workspace':
'cmd-alt-t': 'notifications:trigger-error'
214 changes: 214 additions & 0 deletions packages/notifications/lib/command-logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS202: Simplify dynamic range loops
* DS206: Consider reworking classes to avoid initClass
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
// Originally from lee-dohm/bug-report
// https://github.com/lee-dohm/bug-report/blob/master/lib/command-logger.coffee

// Command names that are ignored and not included in the log. This uses an Object to provide fast
// string matching.
let CommandLogger;
const ignoredCommands = {
'show.bs.tooltip': true,
'shown.bs.tooltip': true,
'hide.bs.tooltip': true,
'hidden.bs.tooltip': true,
'editor:display-updated': true,
'mousewheel': true
};

// Ten minutes in milliseconds.
const tenMinutes = 10 * 60 * 1000;

// Public: Handles logging all of the Pulsar commands for the automatic repro steps feature.
//
// It uses an array as a circular data structure to log only the most recent commands.
module.exports =
(CommandLogger = (function() {
CommandLogger = class CommandLogger {
static initClass() {

// Public: Maximum size of the log.
this.prototype.logSize = 16;
}
static instance() {
return this._instance != null ? this._instance : (this._instance = new CommandLogger);
}

static start() {
return this.instance().start();
}

// Public: Creates a new logger.
constructor() {
this.initLog();
}

start() {
return atom.commands.onWillDispatch(event => {
return this.logCommand(event);
});
}

// Public: Formats the command log for the bug report.
//
// * `externalData` An {Object} containing other information to include in the log.
//
// Returns a {String} of the Markdown for the report.
getText(externalData) {
const lines = [];
const lastTime = Date.now();

this.eachEvent(event => {
if (event.time > lastTime) { return; }
if (!event.name || ((lastTime - event.time) >= tenMinutes)) { return; }
return lines.push(this.formatEvent(event, lastTime));
});

if (externalData) {
lines.push(` ${this.formatTime(0)} ${externalData.title}`);
}

lines.unshift('```');
lines.push('```');
return lines.join("\n");
}

// Public: Gets the latest event from the log.
//
// Returns the event {Object}.
latestEvent() {
return this.eventLog[this.logIndex];
}

// Public: Logs the command.
//
// * `command` Command {Object} to be logged
// * `type` Name {String} of the command
// * `target` {String} describing where the command was triggered
logCommand(command) {
const {type: name, target, time} = command;
if (command.detail != null ? command.detail.jQueryTrigger : undefined) { return; }
if (name in ignoredCommands) { return; }

let event = this.latestEvent();

if (event.name === name) {
return event.count++;
} else {
this.logIndex = (this.logIndex + 1) % this.logSize;
event = this.latestEvent();
event.name = name;
event.targetNodeName = target.nodeName;
event.targetClassName = target.className;
event.targetId = target.id;
event.count = 1;
return event.time = time != null ? time : Date.now();
}
}

// Private: Calculates the time of the last event to be reported.
//
// * `data` Data from an external bug passed in from another package.
//
// Returns the {Date} of the last event that should be reported.
calculateLastEventTime(data) {
if (data) { return data.time; }

let lastTime = null;
this.eachEvent(event => lastTime = event.time);
return lastTime;
}

// Private: Executes a function on each event in chronological order.
//
// This function is used instead of similar underscore functions because the log is held in a
// circular buffer.
//
// * `fn` {Function} to execute for each event in the log.
// * `event` An {Object} describing the event passed to your function.
//
// ## Examples
//
// This code would output the name of each event to the console.
//
// ```coffee
// logger.eachEvent (event) ->
// console.log event.name
// ```
eachEvent(fn) {
for (let offset = 1, end = this.logSize, asc = 1 <= end; asc ? offset <= end : offset >= end; asc ? offset++ : offset--) {
fn(this.eventLog[(this.logIndex + offset) % this.logSize]);
}
}

// Private: Format the command count for reporting.
//
// Returns the {String} format of the command count.
formatCount(count) {
switch (false) {
case !(count < 2): return ' ';
case !(count < 10): return ` ${count}x`;
case !(count < 100): return ` ${count}x`;
}
}

// Private: Formats a command event for reporting.
//
// * `event` Event {Object} to be formatted.
// * `lastTime` {Date} of the last event to report.
//
// Returns the {String} format of the command event.
formatEvent(event, lastTime) {
const {count, time, name, targetNodeName, targetClassName, targetId} = event;
const nodeText = targetNodeName.toLowerCase();
const idText = targetId ? `#${targetId}` : '';
let classText = '';
if (targetClassName != null) { for (var klass of Array.from(targetClassName.split(" "))) { classText += `.${klass}`; } }
return `${this.formatCount(count)} ${this.formatTime(lastTime - time)} ${name} (${nodeText}${idText}${classText})`;
}

// Private: Format the command time for reporting.
//
// * `time` {Date} to format
//
// Returns the {String} format of the command time.
formatTime(time) {
const minutes = Math.floor(time / 60000);
let seconds = Math.floor(((time % 60000) / 1000) * 10) / 10;
if (seconds < 10) { seconds = `0${seconds}`; }
if (Math.floor(seconds) !== seconds) { seconds = `${seconds}.0`; }
return `-${minutes}:${seconds}`;
}

// Private: Initializes the log structure for speed.
initLog() {
this.logIndex = 0;
return this.eventLog = __range__(0, this.logSize, false).map((i) => ({
name: null,
count: 0,
targetNodeName: null,
targetClassName: null,
targetId: null,
time: null
}));
}
};
CommandLogger.initClass();
return CommandLogger;
})());

function __range__(left, right, inclusive) {
let range = [];
let ascending = left < right;
let end = !inclusive ? right : ascending ? right + 1 : right - 1;
for (let i = left; ascending ? i < end : i > end; ascending ? i++ : i--) {
range.push(i);
}
return range;
}
Loading