Skip to content
This repository has been archived by the owner on Apr 1, 2020. It is now read-only.

Commit

Permalink
Notifications (#365)
Browse files Browse the repository at this point in the history
* First version of notifications log

* Adds showing and hiding of notifications panel

* Refactored logs in NeovimInstance and alert in Config to notifications

* Rename notifications to logs

* Improves styling of long stack traces and extracts variables to common.less

* Removes example logs
  • Loading branch information
FrigoEU authored and extr0py committed Apr 14, 2017
1 parent 3194042 commit 0b860a7
Show file tree
Hide file tree
Showing 13 changed files with 377 additions and 14 deletions.
23 changes: 20 additions & 3 deletions browser/src/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,17 +196,34 @@ class Config extends EventEmitter {
public unregisterListener(callback: Function): void {
this.configChanged.removeListener("config-change", callback)
}
// Emitting event is not enough, at startup nobody's listening yet
// so we can't emit the parsing error to anyone when it happens
public getParsingError(): Error | null {
const maybeError = this.getUserRuntimeConfig()
return _.isError(maybeError) ? maybeError : null
}

private applyConfig(): void {
let userRuntimeConfig = {}
let userRuntimeConfigOrError = this.getUserRuntimeConfig()
if (_.isError(userRuntimeConfigOrError)) {
this.emit("logError", userRuntimeConfigOrError)
this.Config = { ...this.DefaultConfig, ...this.DefaultPlatformConfig}
} else {
this.Config = { ...this.DefaultConfig, ...this.DefaultPlatformConfig, ...userRuntimeConfigOrError}
}
}
private getUserRuntimeConfig(): IConfigValues | Error {
let userRuntimeConfig: IConfigValues | null = null
let error: Error | null = null
if (fs.existsSync(this.userJsConfig)) {
try {
userRuntimeConfig = global["require"](this.userJsConfig) // tslint:disable-line no-string-literal
} catch (e) {
alert("Failed to parse " + this.userJsConfig + ":\n" + (<Error>e).message)
e.message = "Failed to parse " + this.userJsConfig + ":\n" + (<Error>e).message
error = e
}
}
this.Config = { ...this.DefaultConfig, ...this.DefaultPlatformConfig, ...userRuntimeConfig }
return error ? error : userRuntimeConfig
}

private notifyListeners(): void {
Expand Down
18 changes: 9 additions & 9 deletions browser/src/NeovimInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class NeovimInstance extends EventEmitter implements INeovimInstance {

this._initPromise = startNeovim(this._pluginManager.getAllRuntimePaths(), filesToOpen)
.then((nv) => {
console.log("NevoimInstance: Neovim started") // tslint:disable-line no-console
this.emit("logInfo", "NeovimInstance: Neovim started")

// Workaround for issue where UI
// can fail to attach if there is a UI-blocking error
Expand All @@ -110,7 +110,7 @@ export class NeovimInstance extends EventEmitter implements INeovimInstance {
this.command("set completeopt=longest,menu")

this._neovim.on("error", (err: Error) => {
console.error(err)
this.emit("logError", err)
})

this._neovim.on("notification", (method: any, args: any) => {
Expand Down Expand Up @@ -141,15 +141,15 @@ export class NeovimInstance extends EventEmitter implements INeovimInstance {
}

} else {
console.warn("Unknown event from oni_plugin_notify: " + pluginMethod)
this.emit("logWarning", "Unknown event from oni_plugin_notify: " + pluginMethod)
}
} else {
console.warn("Unknown notification: " + method)
this.emit("logWarning", "Unknown notification: " + method)
}
})

this._neovim.on("request", (method: any, _args: any, _resp: any) => {
console.warn("Unhandled request: " + method)
this.emit("logWarning", "Unhandled request: " + method)
})

this._neovim.on("disconnect", () => {
Expand All @@ -168,7 +168,7 @@ export class NeovimInstance extends EventEmitter implements INeovimInstance {
// Workaround for bug in neovim/node-client
// The 'uiAttach' method overrides the new 'nvim_ui_attach' method
this._neovim._session.request("nvim_ui_attach", [size.cols, size.rows, startupOptions], (_err?: Error) => {
console.log("Attach success") // tslint:disable-line no-console
this.emit("logInfo", "Attach success")

performance.mark("NeovimInstance.Plugins.Start")
this._pluginManager.startPlugins(this)
Expand Down Expand Up @@ -307,7 +307,7 @@ export class NeovimInstance extends EventEmitter implements INeovimInstance {
const fixedSize = this._config.getValue("debug.fixedSize")
rows = fixedSize.rows
columns = fixedSize.columns
console.warn("Overriding screen size based on debug.fixedSize")
this.emit("logWarning", "Overriding screen size based on debug.fixedSize")
}

if (rows === this._rows && columns === this._cols) {
Expand All @@ -326,7 +326,7 @@ export class NeovimInstance extends EventEmitter implements INeovimInstance {
this._initPromise.then(() => {
this._neovim.uiTryResize(columns, rows, (err?: Error) => {
if (err) {
console.error(err)
this.emit("logError", err)
}
})
})
Expand Down Expand Up @@ -397,7 +397,7 @@ export class NeovimInstance extends EventEmitter implements INeovimInstance {
audio.play()
}
} else {
console.warn("Unhandled command: " + command)
this.emit("logWarning", "Unhandled command: " + command)
}
})
}
Expand Down
7 changes: 7 additions & 0 deletions browser/src/Services/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { IBuffer } from "./../neovim/Buffer"
import { INeovimInstance } from "./../NeovimInstance"
import { PluginManager } from "./../Plugins/PluginManager"

import * as UI from "./../UI/index"

import { CallbackCommand, CommandManager } from "./CommandManager"

export const registerBuiltInCommands = (commandManager: CommandManager, pluginManager: PluginManager, neovimInstance: INeovimInstance) => {
Expand Down Expand Up @@ -52,6 +54,11 @@ export const registerBuiltInCommands = (commandManager: CommandManager, pluginMa

new CallbackCommand("oni.config.openInitVim", "Edit Neovim Config", "Edit configuration file ('init.vim') for Neovim", () => neovimInstance.open("$MYVIMRC")),

new CallbackCommand("oni.editor.showLogs",
"Show Logs",
"Show all logs in the bottom panel",
() => UI.Actions.changeLogsVisibility(true)),

// Add additional commands here
// ...
]
Expand Down
13 changes: 13 additions & 0 deletions browser/src/UI/ActionCreators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import * as State from "./State"
import * as Config from "./../Config"
import * as Actions from "./Actions"
import { events } from "./Events"
import {ILog} from "./Logs"

export const showCompletions = (result: Oni.Plugin.CompletionResult) => (dispatch: Function, getState: Function) => {
dispatch(_showAutoCompletion(result.base, result.completions))
Expand Down Expand Up @@ -185,6 +186,18 @@ export function setConfigValue<K extends keyof Config.IConfigValues>(k: K, v: Co
},
}
}
export const toggleLogFold = (index: number): Actions.IToggleLogFold => ({
type: "TOGGLE_LOG_FOLD",
payload: {index},
})
export const changeLogsVisibility = (visibility: boolean): Actions.IChangeLogsVisibility => ({
type: "CHANGE_LOGS_VISIBILITY",
payload: {visibility},
})
export const makeLog = (log: ILog): Actions.IMakeLog => ({
type: "MAKE_LOG",
payload: {log},
})

export const showNeovimInstallHelp = (): Actions.IShowNeovimInstallHelpAction => ({
type: "SHOW_NEOVIM_INSTALL_HELP",
Expand Down
24 changes: 23 additions & 1 deletion browser/src/UI/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

import * as Config from "./../Config"
import { ILog } from "./Logs"
import { Rectangle } from "./Types"

export interface ISetCursorPositionAction {
Expand Down Expand Up @@ -156,6 +157,24 @@ export interface ISetConfigurationValue<K extends keyof Config.IConfigValues> {
value: Config.IConfigValues[K],
}
}
export interface IToggleLogFold {
type: "TOGGLE_LOG_FOLD"
payload: {
index: number,
}
}
export interface IChangeLogsVisibility {
type: "CHANGE_LOGS_VISIBILITY",
payload: {
visibility: boolean,
}
}
export interface IMakeLog {
type: "MAKE_LOG",
payload: {
log: ILog,
}
}

export interface IShowNeovimInstallHelpAction {
type: "SHOW_NEOVIM_INSTALL_HELP"
Expand Down Expand Up @@ -189,7 +208,10 @@ export type SimpleAction =
IShowCursorColumnAction |
ISetCursorColumnOpacityAction |
ISetCursorLineOpacityAction |
IShowNeovimInstallHelpAction
IShowNeovimInstallHelpAction |
IToggleLogFold |
IChangeLogsVisibility |
IMakeLog

export type ActionWithGeneric<K extends keyof Config.IConfigValues> =
ISetConfigurationValue<K>
6 changes: 6 additions & 0 deletions browser/src/UI/Logs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export type LogType = "success" | "info" | "warning" | "error" | "fatal"
export interface ILog {
type: LogType
message: string
details: string[] | null
}
19 changes: 19 additions & 0 deletions browser/src/UI/Reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,25 @@ export function reducer<K extends keyof Config.IConfigValues> (s: State.IState,
return Object.assign({}, s, {
showNeovimInstallHelp: true,
})
case "TOGGLE_LOG_FOLD":
return Object.assign({}, s, {
logs: s.logs.map((n, i) => {
return i === a.payload.index ?
Object.assign({}, n, {folded: !n.folded}) : n
}),
})
case "CHANGE_LOGS_VISIBILITY":
return Object.assign({}, s, {
logsVisible: a.payload.visibility,
})
case "MAKE_LOG":
const newLog = {
log: a.payload.log,
folded: true,
}
return Object.assign({}, s, {
logs: _.concat(s.logs, newLog),
})
default:
return Object.assign({}, s, {
autoCompletion: autoCompletionReducer(s.autoCompletion, a), // FIXME: null
Expand Down
2 changes: 2 additions & 0 deletions browser/src/UI/RootComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { AutoCompletionContainer } from "./components/AutoCompletion"
import { Cursor } from "./components/Cursor"
import { CursorLine } from "./components/CursorLine"
import { InstallHelp } from "./components/InstallHelp"
import { Logs } from "./components/Logs"
import { MenuContainer } from "./components/Menu"
import { QuickInfoContainer, SignatureHelpContainer } from "./components/QuickInfo"
import * as State from "./State"
Expand All @@ -29,6 +30,7 @@ export class RootComponentRenderer extends React.Component<IRootComponentProps,
<SignatureHelpContainer />
<MenuContainer />
<AutoCompletionContainer />
<Logs />
</div>
}
}
Expand Down
10 changes: 9 additions & 1 deletion browser/src/UI/State.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

import * as Config from "./../Config"
import { ILog } from "./Logs"
import { Rectangle } from "./Types"

export interface IState {
Expand All @@ -23,6 +24,12 @@ export interface IState {
configuration: Config.IConfigValues
showNeovimInstallHelp: boolean

logsVisible: boolean
logs: Array<{
log: ILog,
folded: boolean,
}>

// Dimensions of active window, in pixels
activeWindowDimensions: Rectangle
}
Expand Down Expand Up @@ -58,7 +65,6 @@ export interface IAutoCompletionInfo {
*/
selectedIndex: number
}

export const createDefaultState = (): IState => ({
cursorPixelX: 10,
cursorPixelY: 10,
Expand All @@ -84,5 +90,7 @@ export const createDefaultState = (): IState => ({
cursorColumnOpacity: 0,
backgroundColor: "#000000",
showNeovimInstallHelp: false,
logsVisible: false,
logs: [],
configuration: Config.instance().getValues(),
})
75 changes: 75 additions & 0 deletions browser/src/UI/components/Logs.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
@import (reference) "./common.less";

.logs {
background: @background-color;
position: fixed;
width: 100%;
bottom: 0px;
font-size: 13px;

display: block;
overflow-x: hidden;
overflow-y: auto;

table {
width: 100%;
border-spacing: 0px;
border-collapse: collapse;
table-layout: fixed;
td{
border: 1px solid @border-color;
}
}

.log-unfold-icon{
color: @text-color;
margin-left: @component-padding/2;
}

.logs-header, .log-details-cell{
background-color: @background-color-lighter;
color: @text-color;
padding: @component-padding/2 @component-padding;
border-top: 1px solid @border-color;
}
.log-details{
max-width: 100%;
overflow-x: auto;
}
.logs-header-close {
position: absolute;
right: @component-padding;
}

.log-icon{
width: 30px;
height: 100%;
text-align: center;
padding-top: @component-padding/2;
}
.log-message{
padding: @component-padding/2 @component-padding;
outline: none;
}

.log-detail-line {
white-space: pre;
}

.clickable{
cursor: pointer;
}

.log-fatal, .log-error {
color: @text-color-error;
}
.log-success {
color: @text-color-success;
}
.log-info {
color: @text-color-info;
}
.log-warning {
color: @text-color-warning;
}
}
Loading

0 comments on commit 0b860a7

Please sign in to comment.