Folder restructuring (#86)
This commit is contained in:
149
src/app.js
Normal file
149
src/app.js
Normal file
@@ -0,0 +1,149 @@
|
||||
$(function() {
|
||||
_init('.keymap--edit');
|
||||
|
||||
$('.notification').on('click', '.notification__dismiss', function(e) {
|
||||
$('.notification').hide();
|
||||
}).on('click', '.notification__action--undo', function(e) {
|
||||
$('.notification').hide();
|
||||
$('.sidebar__level-2--item:hidden').show().click();
|
||||
});;
|
||||
|
||||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
});
|
||||
|
||||
// =======================
|
||||
// Menu-item functionality LEGACY TODO remove
|
||||
// =======================
|
||||
$('.pane-title__name, .pane-title__abbrev').on('mouseover', function() {
|
||||
$(this).addClass('active');
|
||||
}).on('mouseout', function() {
|
||||
if (!$(this).is(':focus')) {
|
||||
$(this).removeClass('active');
|
||||
}
|
||||
}).on('focusout', function() {
|
||||
$(this).removeClass('active');
|
||||
});
|
||||
|
||||
$('.keymap__is-default').on('click', function() {
|
||||
$(this).toggleClass('fa-star-o');
|
||||
});
|
||||
|
||||
// ========================
|
||||
// Keymap related settings.
|
||||
// ========================
|
||||
$('button.uhk__layer-switcher').on('click', function(e) {
|
||||
var button = $(this),
|
||||
layerOrder = ['base', 'mod', 'fn', 'mouse'],
|
||||
currentButton = $('button.uhk__layer-switcher.current'),
|
||||
slideLayer = button.data('layer'),
|
||||
slideNumber = layerOrder.indexOf(slideLayer),
|
||||
currentSlideLayer = currentButton.data('layer'),
|
||||
currentSlideNumber = layerOrder.indexOf(currentSlideLayer),
|
||||
slide = $('.uhk__layer-wrapper--' + slideLayer),
|
||||
currentSlide = $('.uhk__layer-wrapper.current'),
|
||||
slideWidth = currentSlide.width() + 'px';
|
||||
|
||||
if (slideNumber < currentSlideNumber) {
|
||||
// From left to right
|
||||
currentSlide.css('left', 0);
|
||||
slide.css('left', '-' + slideWidth);
|
||||
|
||||
currentSlide.animate({left: slideWidth}, function() {
|
||||
$(this).removeClass('current');
|
||||
});
|
||||
slide.animate({left: 0}, function() {
|
||||
$(this).addClass('current');
|
||||
});
|
||||
|
||||
currentButton.removeClass('current btn-primary').addClass('btn-default');
|
||||
button.addClass('current btn-primary').removeClass('btn-default').blur();
|
||||
} else if (slideNumber != currentSlideNumber) {
|
||||
// From right to left
|
||||
currentSlide.css({left: 0});
|
||||
slide.css({left: slideWidth});
|
||||
|
||||
currentSlide.animate({left: '-' + slideWidth}, function() {
|
||||
$(this).removeClass('current');
|
||||
});
|
||||
slide.animate({left: 0}, function() {
|
||||
$(this).addClass('current');
|
||||
});
|
||||
|
||||
currentButton.removeClass('current btn-primary').addClass('btn-default');
|
||||
button.addClass('current btn-primary').addClass('btn-default').blur();
|
||||
}
|
||||
});
|
||||
|
||||
$('.keymap__remove').on('click', function(e) {
|
||||
// Mimic the removal of a keymap with undo option.
|
||||
$('.sidebar__level-2--item:hidden').remove();
|
||||
$('.sidebar__level-2--item.active').hide();
|
||||
|
||||
// Show the factory keymap after removal of a keymap.
|
||||
$('.sidebar__level-2--item:first').click();
|
||||
$('.notification').show();
|
||||
});
|
||||
|
||||
// Based on: http://stackoverflow.com/a/24933495
|
||||
$('img.uhk').each(function(){
|
||||
var $img = $(this);
|
||||
var imgID = $img.attr('id');
|
||||
var imgClass = $img.attr('class');
|
||||
var imgURL = $img.attr('src');
|
||||
var imgSelector = '.' + imgClass.replace(' ', '.')
|
||||
|
||||
$.get(imgURL, function(data) {
|
||||
// Get the SVG tag, ignore the rest
|
||||
var $svg = $(data).find('svg');
|
||||
|
||||
// Add replaced image's ID to the new SVG
|
||||
if(typeof imgID !== 'undefined') {
|
||||
$svg = $svg.attr('id', imgID);
|
||||
}
|
||||
// Add replaced image's classes to the new SVG
|
||||
if(typeof imgClass !== 'undefined') {
|
||||
$svg = $svg.attr('class', imgClass+' replaced-svg');
|
||||
}
|
||||
|
||||
// Remove any invalid XML tags as per http://validator.w3.org
|
||||
$svg = $svg.removeAttr('xmlns:a');
|
||||
|
||||
// Check if the viewport is set, else we gonna set it if we can.
|
||||
if(!$svg.attr('viewBox') && $svg.attr('height') && $svg.attr('width')) {
|
||||
$svg.attr('viewBox', '0 0 ' + $svg.attr('height') + ' ' + $svg.attr('width'))
|
||||
}
|
||||
|
||||
// Replace image with new SVG
|
||||
$img.replaceWith($svg);
|
||||
$('.keyboard-slider').height($svg.height());
|
||||
|
||||
// Quick fix as jQuery 2.1.4 addClass() method is not working on SVG elements.
|
||||
var finalClasses = $svg.attr('class');
|
||||
|
||||
$('#left-parts rect, #right-parts rect', imgSelector).on('click', function() {
|
||||
var _popup = $('.key-editor__popup'),
|
||||
rectB7 = $('rect#b7', $svg);
|
||||
if (_popup.is(':hidden')) {
|
||||
$svg.attr('class', finalClasses + ' faded');
|
||||
_popup.show();
|
||||
rectB7.attr('class', 'active');
|
||||
} else {
|
||||
$svg.attr('class', finalClasses);
|
||||
_popup.hide();
|
||||
rectB7.attr('class', '');
|
||||
}
|
||||
});
|
||||
|
||||
}, 'xml');
|
||||
});
|
||||
});
|
||||
|
||||
function _init(view) {
|
||||
switch (view) {
|
||||
case '.keymap--edit':
|
||||
var h = $('.uhk--base-layer').height();
|
||||
$('.keyboard-slider').height(h + 'px');
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,10 @@ import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { LocationStrategy, HashLocationStrategy } from '@angular/common';
|
||||
|
||||
import { APP_ROUTER_PROVIDERS } from './main-app.routes';
|
||||
|
||||
import { DataProviderService } from './services/data-provider.service';
|
||||
import { MapperService } from './services/mapper.service';
|
||||
|
||||
import { MainAppComponent } from './main-app.component';
|
||||
import { MainAppComponent, APP_ROUTER_PROVIDERS } from './main-app';
|
||||
import { KeymapComponent } from './components/keymap';
|
||||
import { MacroComponent } from './components/macro';
|
||||
import { LegacyLoaderComponent } from './components/legacy-loader';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
import { Layers } from '../../../config-serializer/config-items/Layers';
|
||||
import { Layers } from '../../config-serializer/config-items/Layers';
|
||||
import { UhkConfigurationService } from '../../services/uhk-configuration.service';
|
||||
import { Keymap } from '../../../config-serializer/config-items/Keymap';
|
||||
import { Keymap } from '../../config-serializer/config-items/Keymap';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {Component, OnInit, Input, Output, EventEmitter, ViewChild} from '@angular/core';
|
||||
import {NgSwitch, NgSwitchCase} from '@angular/common';
|
||||
|
||||
import {KeyAction} from '../../../config-serializer/config-items/KeyAction';
|
||||
import {KeyAction} from '../../config-serializer/config-items/KeyAction';
|
||||
|
||||
import {KeypressTabComponent} from './tab/keypress/keypress-tab.component';
|
||||
import {LayerTabComponent} from './tab/layer/layer-tab.component';
|
||||
@@ -11,11 +11,11 @@ import {KeymapTabComponent} from './tab/keymap/keymap-tab.component';
|
||||
import {NoneTabComponent} from './tab/none/none-tab.component';
|
||||
|
||||
import {Tab} from './tab/tab';
|
||||
import {KeystrokeAction} from '../../../config-serializer/config-items/KeystrokeAction';
|
||||
import {SwitchLayerAction} from '../../../config-serializer/config-items/SwitchLayerAction';
|
||||
import {MouseAction} from '../../../config-serializer/config-items/MouseAction';
|
||||
import {PlayMacroAction} from '../../../config-serializer/config-items/PlayMacroAction';
|
||||
import {SwitchKeymapAction} from '../../../config-serializer/config-items/SwitchKeymapAction';
|
||||
import {KeystrokeAction} from '../../config-serializer/config-items/KeystrokeAction';
|
||||
import {SwitchLayerAction} from '../../config-serializer/config-items/SwitchLayerAction';
|
||||
import {MouseAction} from '../../config-serializer/config-items/MouseAction';
|
||||
import {PlayMacroAction} from '../../config-serializer/config-items/PlayMacroAction';
|
||||
import {SwitchKeymapAction} from '../../config-serializer/config-items/SwitchKeymapAction';
|
||||
|
||||
enum TabName {
|
||||
Keypress,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {Component, OnInit, Input} from '@angular/core';
|
||||
|
||||
import {UhkConfigurationService} from '../../../../services/uhk-configuration.service';
|
||||
import {Keymap} from '../../../../../config-serializer/config-items/Keymap';
|
||||
import {KeyAction} from '../../../../../config-serializer/config-items/KeyAction';
|
||||
import {Keymap} from '../../../../config-serializer/config-items/Keymap';
|
||||
import {KeyAction} from '../../../../config-serializer/config-items/KeyAction';
|
||||
import {SvgKeyboardComponent} from '../../../svg/keyboard';
|
||||
import {Tab} from '../tab';
|
||||
import {SwitchKeymapAction} from '../../../../../config-serializer/config-items/SwitchKeymapAction';
|
||||
import {SwitchKeymapAction} from '../../../../config-serializer/config-items/SwitchKeymapAction';
|
||||
|
||||
import {Select2Component, Select2OptionData} from 'ng2-select2/ng2-select2';
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ import {Component, OnInit, Input} from '@angular/core';
|
||||
|
||||
import {Select2Component, Select2OptionData} from 'ng2-select2/ng2-select2';
|
||||
|
||||
import {KeyAction} from '../../../../../config-serializer/config-items/KeyAction';
|
||||
import {KeystrokeAction} from '../../../../../config-serializer/config-items/KeystrokeAction';
|
||||
import {KeyAction} from '../../../../config-serializer/config-items/KeyAction';
|
||||
import {KeystrokeAction} from '../../../../config-serializer/config-items/KeystrokeAction';
|
||||
|
||||
import {IconComponent} from '../../widgets/icon';
|
||||
import {CaptureKeystrokeButtonComponent} from '../../widgets/capture-keystroke';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {Component, OnInit, Input, ViewChild} from '@angular/core';
|
||||
import {NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common';
|
||||
|
||||
import {LayerName, SwitchLayerAction} from '../../../../../config-serializer/config-items/SwitchLayerAction';
|
||||
import {KeyAction} from '../../../../../config-serializer/config-items/KeyAction';
|
||||
import {LayerName, SwitchLayerAction} from '../../../../config-serializer/config-items/SwitchLayerAction';
|
||||
import {KeyAction} from '../../../../config-serializer/config-items/KeyAction';
|
||||
|
||||
import {Select2Component, Select2OptionData} from 'ng2-select2/ng2-select2';
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { Component, OnInit, OnChanges, Input } from '@angular/core';
|
||||
|
||||
import {MacroAction} from '../../../../../config-serializer/config-items/MacroAction';
|
||||
import {DelayMacroAction} from '../../../../../config-serializer/config-items/DelayMacroAction';
|
||||
import {HoldModifiersMacroAction} from '../../../../../config-serializer/config-items/HoldModifiersMacroAction';
|
||||
import {MoveMouseMacroAction} from '../../../../../config-serializer/config-items/MoveMouseMacroAction';
|
||||
import {PressModifiersMacroAction} from '../../../../../config-serializer/config-items/PressModifiersMacroAction';
|
||||
import {ReleaseModifiersMacroAction} from '../../../../../config-serializer/config-items/ReleaseModifiersMacroAction';
|
||||
import {ScrollMouseMacroAction} from '../../../../../config-serializer/config-items/ScrollMouseMacroAction';
|
||||
import {TextMacroAction} from '../../../../../config-serializer/config-items/TextMacroAction';
|
||||
import {MacroAction} from '../../../../config-serializer/config-items/MacroAction';
|
||||
import {DelayMacroAction} from '../../../../config-serializer/config-items/DelayMacroAction';
|
||||
import {HoldModifiersMacroAction} from '../../../../config-serializer/config-items/HoldModifiersMacroAction';
|
||||
import {MoveMouseMacroAction} from '../../../../config-serializer/config-items/MoveMouseMacroAction';
|
||||
import {PressModifiersMacroAction} from '../../../../config-serializer/config-items/PressModifiersMacroAction';
|
||||
import {ReleaseModifiersMacroAction} from '../../../../config-serializer/config-items/ReleaseModifiersMacroAction';
|
||||
import {ScrollMouseMacroAction} from '../../../../config-serializer/config-items/ScrollMouseMacroAction';
|
||||
import {TextMacroAction} from '../../../../config-serializer/config-items/TextMacroAction';
|
||||
|
||||
import {IconComponent} from '../../widgets/icon';
|
||||
|
||||
import {KeyModifiers} from '../../../../../config-serializer/config-items/KeyModifiers';
|
||||
import {KeyModifiers} from '../../../../config-serializer/config-items/KeyModifiers';
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {Component, OnInit, Input} from '@angular/core';
|
||||
|
||||
import {UhkConfigurationService} from '../../../../services/uhk-configuration.service';
|
||||
import {Macro} from '../../../../../config-serializer/config-items/Macro';
|
||||
import {KeyAction} from '../../../../../config-serializer/config-items/KeyAction';
|
||||
import {PlayMacroAction} from '../../../../../config-serializer/config-items/PlayMacroAction';
|
||||
import {Macro} from '../../../../config-serializer/config-items/Macro';
|
||||
import {KeyAction} from '../../../../config-serializer/config-items/KeyAction';
|
||||
import {PlayMacroAction} from '../../../../config-serializer/config-items/PlayMacroAction';
|
||||
|
||||
import {Tab} from '../tab';
|
||||
import {MacroItemComponent} from './macro-item.component';
|
||||
|
||||
@@ -2,8 +2,8 @@ import {Component, OnInit, Input} from '@angular/core';
|
||||
import {NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common';
|
||||
|
||||
import {Tab} from '../tab';
|
||||
import {KeyAction} from '../../../../../config-serializer/config-items/KeyAction';
|
||||
import {MouseAction, MouseActionParam} from '../../../../../config-serializer/config-items/MouseAction';
|
||||
import {KeyAction} from '../../../../config-serializer/config-items/KeyAction';
|
||||
import {MouseAction, MouseActionParam} from '../../../../config-serializer/config-items/MouseAction';
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {Component, OnInit } from '@angular/core';
|
||||
|
||||
import {Tab} from '../tab';
|
||||
import {NoneAction} from '../../../../../config-serializer/config-items/NoneAction';
|
||||
import {NoneAction} from '../../../../config-serializer/config-items/NoneAction';
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {KeyAction} from '../../../../config-serializer/config-items/KeyAction';
|
||||
import {KeyAction} from '../../../config-serializer/config-items/KeyAction';
|
||||
|
||||
export interface Tab {
|
||||
keyActionValid(): boolean;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { Keymap } from '../../../config-serializer/config-items/Keymap';
|
||||
import { Keymap } from '../../config-serializer/config-items/Keymap';
|
||||
import { UhkConfigurationService } from '../../services/uhk-configuration.service';
|
||||
import { Macro } from '../../../config-serializer/config-items/Macro';
|
||||
import { Macro } from '../../config-serializer/config-items/Macro';
|
||||
import { ROUTER_DIRECTIVES } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, OnInit, Input, Output, EventEmitter} from '@angular/core';
|
||||
|
||||
import {Module} from '../../../../config-serializer/config-items/Module';
|
||||
import {Module} from '../../../config-serializer/config-items/Module';
|
||||
import {SvgModule, SvgModuleComponent} from '../module';
|
||||
import {DataProviderService} from '../../../services/data-provider.service';
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Component, OnInit, Input, OnChanges, SimpleChange } from '@angular/core';
|
||||
|
||||
import {KeyAction} from '../../../../../config-serializer/config-items/KeyAction';
|
||||
import {KeystrokeAction} from '../../../../../config-serializer/config-items/KeystrokeAction';
|
||||
import {KeyModifiers} from '../../../../../config-serializer/config-items/KeyModifiers';
|
||||
import {PlayMacroAction} from '../../../../../config-serializer/config-items/PlayMacroAction';
|
||||
import {SwitchLayerAction, LayerName} from '../../../../../config-serializer/config-items/SwitchLayerAction';
|
||||
import {SwitchKeymapAction} from '../../../../../config-serializer/config-items/SwitchKeymapAction';
|
||||
import {UhkConfiguration} from '../../../../../config-serializer/config-items/UhkConfiguration';
|
||||
import {KeyAction} from '../../../../config-serializer/config-items/KeyAction';
|
||||
import {KeystrokeAction} from '../../../../config-serializer/config-items/KeystrokeAction';
|
||||
import {KeyModifiers} from '../../../../config-serializer/config-items/KeyModifiers';
|
||||
import {PlayMacroAction} from '../../../../config-serializer/config-items/PlayMacroAction';
|
||||
import {SwitchLayerAction, LayerName} from '../../../../config-serializer/config-items/SwitchLayerAction';
|
||||
import {SwitchKeymapAction} from '../../../../config-serializer/config-items/SwitchKeymapAction';
|
||||
import {UhkConfiguration} from '../../../../config-serializer/config-items/UhkConfiguration';
|
||||
import {UhkConfigurationService} from '../../../../services/uhk-configuration.service';
|
||||
import {MapperService} from '../../../../services/mapper.service';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component, OnInit, OnChanges, Input } from '@angular/core';
|
||||
|
||||
import { KeystrokeAction } from '../../../../../config-serializer/config-items/KeystrokeAction';
|
||||
import { KeyModifiers } from '../../../../../config-serializer/config-items/KeyModifiers';
|
||||
import { KeystrokeAction } from '../../../../config-serializer/config-items/KeystrokeAction';
|
||||
import { KeyModifiers } from '../../../../config-serializer/config-items/KeyModifiers';
|
||||
import { MapperService } from '../../../../services/mapper.service';
|
||||
|
||||
class SvgAttributes {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
|
||||
import { SvgKeyboardKey, SvgKeyboardKeyComponent } from '../keys';
|
||||
import {KeyAction} from '../../../../config-serializer/config-items/KeyAction';
|
||||
import {KeyAction} from '../../../config-serializer/config-items/KeyAction';
|
||||
|
||||
@Component({
|
||||
selector: 'g[svg-module]',
|
||||
|
||||
@@ -3,8 +3,8 @@ import {
|
||||
state, animate, transition, trigger
|
||||
} from '@angular/core';
|
||||
|
||||
import { KeyAction } from '../../../../config-serializer/config-items/KeyAction';
|
||||
import { Layer } from '../../../../config-serializer/config-items/Layer';
|
||||
import { KeyAction } from '../../../config-serializer/config-items/KeyAction';
|
||||
import { Layer } from '../../../config-serializer/config-items/Layer';
|
||||
|
||||
@Component({
|
||||
selector: 'svg-keyboard-wrap',
|
||||
|
||||
54
src/config-serializer/ClassArray.ts
Normal file
54
src/config-serializer/ClassArray.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import {Serializable} from './Serializable';
|
||||
import {UhkBuffer} from './UhkBuffer';
|
||||
|
||||
export abstract class ClassArray<T extends Serializable<T>> extends Serializable<ClassArray<T>> {
|
||||
|
||||
elements: T[] = [];
|
||||
|
||||
_fromJsObject(jsObjects: any): ClassArray<T> {
|
||||
for (let jsObject of jsObjects) {
|
||||
this.elements.push(this.jsObjectToClass(jsObject));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): ClassArray<T> {
|
||||
let arrayLength = buffer.readCompactLength();
|
||||
|
||||
if (buffer.enableDump) {
|
||||
buffer.enableDump = false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < arrayLength; i++) {
|
||||
this.elements.push(this.binaryToClass(buffer));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
let array: any[] = [];
|
||||
for (let element of this.elements) {
|
||||
array.push(element.toJsObject());
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeCompactLength(this.elements.length);
|
||||
|
||||
if (buffer.enableDump) {
|
||||
buffer.enableDump = false;
|
||||
}
|
||||
|
||||
for (let element of this.elements) {
|
||||
element.toBinary(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<${this.constructor.name} length="${this.elements.length}">`;
|
||||
}
|
||||
|
||||
abstract jsObjectToClass(jsObject: any): T;
|
||||
abstract binaryToClass(buffer: UhkBuffer): T;
|
||||
}
|
||||
3
src/config-serializer/Function.d.ts
vendored
Normal file
3
src/config-serializer/Function.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
interface Function {
|
||||
name: string;
|
||||
}
|
||||
87
src/config-serializer/README.md
Normal file
87
src/config-serializer/README.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# Configuration serializer
|
||||
|
||||
This directory contains the configuration serializer of Agent.
|
||||
|
||||
The configuration of the UHK is unusually complex for a keyboard, and is composed of a number of items of different types, including keymaps, layers, macros, and the like. This is a supposed to be a short guide for the aspiring hacker. Let's get right into it!
|
||||
|
||||
## Setup
|
||||
|
||||
Given that the development dependencies are installed on your system you should be able to build the configuration serializer tester by executing `npm run build:test` in this directory, then start the test by running `node test-serializer.js`.
|
||||
|
||||
## Configuration representations
|
||||
|
||||
There are 3 different representations of the configuration, each filling a specific purpose.
|
||||
|
||||
The **JavaScript representation** is optimally suited to be serialized as JSON, and saved to the file system, or transmitted over the network. As a plaintext format, it's human-readable and easily editable. See [uhk-config.json](uhk-config.json) for an example configuration.
|
||||
|
||||
The **TypeScript representation** is structurally similar to the JavaScript representation, but it features strongly typed TypeScript objects instead of typeless JavaScript objects. This representation is meant to be used by Agent. Extensive, per-property [assertion](assert.ts) takes place upon initializing the TypeScript objects to ensure the integrity of the configuration.
|
||||
|
||||
The **binary representation** is meant to be written to, and read from the EEPROM of the UHK. It's designed to be very compact in order to maximize the use of the 32kbyte EEPROM space.
|
||||
|
||||
## Configuration item types
|
||||
|
||||
Each configuration item belongs to a specific type. The following types are available:
|
||||
|
||||
**Primitive types** are integers of different sizes, and string. See [UhkBuffer](UhkBuffer.ts) which implements all the primitive types.
|
||||
|
||||
**Compound types** are composed of primitive types, and/or compound types. All compound types must descend from the [Serializable](Serializable.ts) class, and saved into the [config-items](config-items) directory.
|
||||
|
||||
**Array type** is a special compound type which is composed of a sequence of items of a specific type. Array items must descend from the [ClassArray](ClassArray.ts) class.
|
||||
|
||||
## Dumping serialization
|
||||
|
||||
The serialization of configuration items is a complicated business, and many things can go wrong. That's the exact reason why serialization can be dumped to ease debugging. All you have to do is to set `Serializable.enableDump` to `true`, and you'll see something like the following upon serialization actions:
|
||||
|
||||
```
|
||||
KeyActions.fromJsObject: [{"keyActionType":"none"},{"keyActionType":"keystroke","scancode":110},{"keyActionType":"keystrokeModifiers","modifierMask":33},{"keyActionType":"keystrokeWithM...
|
||||
NoneAction.fromJsObject: {"keyActionType":"none"} => <NoneAction>
|
||||
KeystrokeAction.fromJsObject: {"keyActionType":"keystroke","scancode":110} => <KeystrokeAction scancode="110">
|
||||
KeystrokeModifiersAction.fromJsObject: {"keyActionType":"keystrokeModifiers","modifierMask":33} => <KeystrokeModifiersAction modifierMask="33">
|
||||
KeystrokeWithModifiersAction.fromJsObject: {"keyActionType":"keystrokeWithModifiers","scancode":120,"modifierMask":16} => <KeystrokeWithModifiersAction scancode="120" modifierMask="16">
|
||||
SwitchLayerAction.fromJsObject: {"keyActionType":"switchLayer","layer":"fn","toggle":false} => <SwitchLayerAction layer="1" toggle="false">
|
||||
DualRoleKeystrokeAction.fromJsObject: {"keyActionType":"dualRoleKeystroke","scancode":111,"longPressAction":"mod"} => <DualRoleKeystrokeAction scancode="111" longPressAction="8">
|
||||
MouseAction.fromJsObject: {"keyActionType":"mouse","mouseAction":"scrollDown"} => <MouseAction mouseAction="8">
|
||||
PlayMacroAction.fromJsObject: {"keyActionType":"playMacro","macroId":0} => <PlayMacroAction macroId="0">
|
||||
SwitchKeymapAction.fromJsObject: {"keyActionType":"switchKeymap","keymapId":1} => <SwitchKeymapAction keymapId="1">
|
||||
KeyActions.toBinary: <KeyActions length="9"> => ['u8(9)]
|
||||
NoneAction.toBinary: <NoneAction> => ['u8(0)]
|
||||
KeystrokeAction.toBinary: <KeystrokeAction scancode="110"> => ['u8(1), u8(110)]
|
||||
KeystrokeModifiersAction.toBinary: <KeystrokeModifiersAction modifierMask="33"> => ['u8(2), u8(33)]
|
||||
KeystrokeWithModifiersAction.toBinary: <KeystrokeWithModifiersAction scancode="120" modifierMask="16"> => ['u8(3), u8(120), u8(16)]
|
||||
SwitchLayerAction.toBinary: <SwitchLayerAction layer="1" toggle="false"> => ['u8(5), u8(1)]
|
||||
DualRoleKeystrokeAction.toBinary: <DualRoleKeystrokeAction scancode="111" longPressAction="8"> => ['u8(4), u8(111), u8(8)]
|
||||
MouseAction.toBinary: <MouseAction mouseAction="8"> => ['u8(7), u8(8)]
|
||||
PlayMacroAction.toBinary: <PlayMacroAction macroId="0"> => ['u8(8), u8(0)]
|
||||
SwitchKeymapAction.toBinary: <SwitchKeymapAction keymapId="1"> => ['u8(6), u8(1)]
|
||||
KeyActions.fromBinary: [u8(9)]
|
||||
NoneAction.fromBinary: [u8(0)] => <NoneAction>
|
||||
KeystrokeAction.fromBinary: [u8(1), u8(110)] => <KeystrokeAction scancode="110">
|
||||
KeystrokeModifiersAction.fromBinary: [u8(2), u8(33)] => <KeystrokeModifiersAction modifierMask="33">
|
||||
KeystrokeWithModifiersAction.fromBinary: [u8(3), u8(120), u8(16)] => <KeystrokeWithModifiersAction scancode="120" modifierMask="16">
|
||||
SwitchLayerAction.fromBinary: [u8(5), u8(1)] => <SwitchLayerAction layer="1" toggle="false">
|
||||
DualRoleKeystrokeAction.fromBinary: [u8(4), u8(111), u8(8)] => <DualRoleKeystrokeAction scancode="111" longPressAction="8">
|
||||
MouseAction.fromBinary: [u8(7), u8(8)] => <MouseAction mouseAction="8">
|
||||
PlayMacroAction.fromBinary: [u8(8), u8(0)] => <PlayMacroAction macroId="0">
|
||||
SwitchKeymapAction.fromBinary: [u8(6), u8(1)] => <SwitchKeymapAction keymapId="1">
|
||||
KeyActions.toJsObject: <KeyActions length="9">
|
||||
NoneAction.toJsObject: <NoneAction> => {"keyActionType":"none"}
|
||||
KeystrokeAction.toJsObject: <KeystrokeAction scancode="110"> => {"keyActionType":"keystroke","scancode":110}
|
||||
KeystrokeModifiersAction.toJsObject: <KeystrokeModifiersAction modifierMask="33"> => {"keyActionType":"keystrokeModifiers","modifierMask":33}
|
||||
KeystrokeWithModifiersAction.toJsObject: <KeystrokeWithModifiersAction scancode="120" modifierMask="16"> => {"keyActionType":"keystrokeWithModifiers","scancode":120,"modifierMask":16}
|
||||
SwitchLayerAction.toJsObject: <SwitchLayerAction layer="1" toggle="false"> => {"keyActionType":"switchLayer","layer":"fn","toggle":false}
|
||||
DualRoleKeystrokeAction.toJsObject: <DualRoleKeystrokeAction scancode="111" longPressAction="8"> => {"keyActionType":"dualRoleKeystroke","scancode":111,"longPressAction":"mod"}
|
||||
MouseAction.toJsObject: <MouseAction mouseAction="8"> => {"keyActionType":"mouse","mouseAction":"scrollDown"}
|
||||
PlayMacroAction.toJsObject: <PlayMacroAction macroId="0"> => {"keyActionType":"playMacro","macroId":0}
|
||||
SwitchKeymapAction.toJsObject: <SwitchKeymapAction keymapId="1"> => {"keyActionType":"switchKeymap","keymapId":1}
|
||||
```
|
||||
|
||||
## Testing the serializer
|
||||
|
||||
[test-serializer.ts](test-serializer.ts) is designed to test the serializer by taking [uhk-config.json](uhk-config.json), and transforming it to TypeScript representation, then to binary representation, then finally back to JavaScript representation. This should exercise every major code path.
|
||||
|
||||
If the testing is successful the following should be displayed:
|
||||
|
||||
```
|
||||
JSON configurations are identical.
|
||||
Binary configurations are identical.
|
||||
```
|
||||
74
src/config-serializer/Serializable.ts
Normal file
74
src/config-serializer/Serializable.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
/// <references path="Function.d.ts">
|
||||
|
||||
import {UhkBuffer} from './UhkBuffer';
|
||||
|
||||
export abstract class Serializable<T> {
|
||||
|
||||
private static depth = 0;
|
||||
private static maxDisplayedJsonLength = 160;
|
||||
private static enableDump = false;
|
||||
|
||||
fromJsObject(jsObject: any): T {
|
||||
this.dump(`${this.getIndentation()}${this.constructor.name}.fromJsObject: ` +
|
||||
`${this.strintifyJsObject(jsObject)}\n`);
|
||||
Serializable.depth++;
|
||||
let value = this._fromJsObject(jsObject);
|
||||
Serializable.depth--;
|
||||
this.dump(`${this.getIndentation()}=> ${value}\n`);
|
||||
return value;
|
||||
}
|
||||
|
||||
fromBinary(buffer: UhkBuffer): T {
|
||||
this.dump(`\n${this.getIndentation()}${this.constructor.name}.fromBinary: [`);
|
||||
Serializable.depth++;
|
||||
buffer.enableDump = Serializable.enableDump;
|
||||
let value = this._fromBinary(buffer);
|
||||
buffer.enableDump = false;
|
||||
Serializable.depth--;
|
||||
this.dump(`]\n${this.getIndentation()}=> ${value}`);
|
||||
return value;
|
||||
}
|
||||
|
||||
toJsObject(): any {
|
||||
this.dump(`${this.getIndentation()}${this.constructor.name}.toJsObject: ${this}\n`);
|
||||
Serializable.depth++;
|
||||
let value = this._toJsObject();
|
||||
Serializable.depth--;
|
||||
this.dump(`${this.getIndentation()}=> ${this.strintifyJsObject(value)}\n`);
|
||||
return value;
|
||||
}
|
||||
|
||||
// TODO: remove parameter and return the buffer
|
||||
toBinary(buffer: UhkBuffer): void {
|
||||
this.dump(`\n${this.getIndentation()}${this.constructor.name}.toBinary: ${this} [`);
|
||||
Serializable.depth++;
|
||||
buffer.enableDump = Serializable.enableDump;
|
||||
let value = this._toBinary(buffer);
|
||||
buffer.enableDump = false;
|
||||
Serializable.depth--;
|
||||
this.dump(`]`);
|
||||
return value;
|
||||
}
|
||||
|
||||
abstract _fromJsObject(jsObject: any): T;
|
||||
abstract _fromBinary(buffer: UhkBuffer): T;
|
||||
abstract _toJsObject(): any;
|
||||
abstract _toBinary(buffer: UhkBuffer): void;
|
||||
|
||||
private dump(value: any) {
|
||||
if (Serializable.enableDump) {
|
||||
process.stdout.write(value);
|
||||
}
|
||||
}
|
||||
|
||||
private getIndentation() {
|
||||
return new Array(Serializable.depth + 1).join(' ');
|
||||
}
|
||||
|
||||
private strintifyJsObject(jsObject: any): string {
|
||||
let json = JSON.stringify(jsObject);
|
||||
return json.length > Serializable.maxDisplayedJsonLength
|
||||
? json.substr(0, Serializable.maxDisplayedJsonLength) + '...'
|
||||
: json;
|
||||
}
|
||||
}
|
||||
189
src/config-serializer/UhkBuffer.ts
Normal file
189
src/config-serializer/UhkBuffer.ts
Normal file
@@ -0,0 +1,189 @@
|
||||
export class UhkBuffer {
|
||||
|
||||
private static eepromSize = 32 * 1024;
|
||||
private static maxCompactLength = 0xFFFF;
|
||||
private static longCompactLengthPrefix = 0xFF;
|
||||
private static stringEncoding = 'utf8';
|
||||
private static isFirstElementToDump = false;
|
||||
|
||||
offset: number;
|
||||
private _enableDump = false;
|
||||
|
||||
private buffer: Buffer;
|
||||
private bytesToBacktrack: number;
|
||||
|
||||
constructor() {
|
||||
this.offset = 0;
|
||||
this.bytesToBacktrack = 0;
|
||||
this.buffer = new Buffer(UhkBuffer.eepromSize);
|
||||
this.buffer.fill(0);
|
||||
}
|
||||
|
||||
readInt8(): number {
|
||||
let value = this.buffer.readInt8(this.offset);
|
||||
this.dump(`i8(${value})`);
|
||||
this.bytesToBacktrack = 1;
|
||||
this.offset += this.bytesToBacktrack;
|
||||
return value;
|
||||
}
|
||||
|
||||
writeInt8(value: number): void {
|
||||
this.dump(`i8(${value})`);
|
||||
this.buffer.writeInt8(value, this.offset);
|
||||
this.offset += 1;
|
||||
}
|
||||
|
||||
readUInt8(): number {
|
||||
let value = this.buffer.readUInt8(this.offset);
|
||||
this.dump(`u8(${value})`);
|
||||
this.bytesToBacktrack = 1;
|
||||
this.offset += this.bytesToBacktrack;
|
||||
return value;
|
||||
}
|
||||
|
||||
writeUInt8(value: number): void {
|
||||
this.dump(`u8(${value})`);
|
||||
this.buffer.writeUInt8(value, this.offset);
|
||||
this.offset += 1;
|
||||
}
|
||||
|
||||
readInt16(): number {
|
||||
let value = this.buffer.readInt16LE(this.offset);
|
||||
this.dump(`i16(${value})`);
|
||||
this.bytesToBacktrack = 2;
|
||||
this.offset += this.bytesToBacktrack;
|
||||
return value;
|
||||
}
|
||||
|
||||
writeInt16(value: number): void {
|
||||
this.dump(`i16(${value})`);
|
||||
this.buffer.writeInt16LE(value, this.offset);
|
||||
this.offset += 2;
|
||||
}
|
||||
|
||||
readUInt16(): number {
|
||||
let value = this.buffer.readUInt16LE(this.offset);
|
||||
this.dump(`u16(${value})`);
|
||||
this.bytesToBacktrack = 2;
|
||||
this.offset += this.bytesToBacktrack;
|
||||
return value;
|
||||
}
|
||||
|
||||
writeUInt16(value: number): void {
|
||||
this.dump(`u16(${value})`);
|
||||
this.buffer.writeUInt16LE(value, this.offset);
|
||||
this.offset += 2;
|
||||
}
|
||||
|
||||
readInt32(): number {
|
||||
let value = this.buffer.readInt32LE(this.offset);
|
||||
this.dump(`i32(${value})`);
|
||||
this.bytesToBacktrack = 4;
|
||||
this.offset += this.bytesToBacktrack;
|
||||
return value;
|
||||
}
|
||||
|
||||
writeInt32(value: number): void {
|
||||
this.dump(`i32(${value})`);
|
||||
this.buffer.writeInt32LE(value, this.offset);
|
||||
this.offset += 4;
|
||||
}
|
||||
|
||||
readUInt32(): number {
|
||||
let value = this.buffer.readUInt32LE(this.offset);
|
||||
this.dump(`u32(${value})`);
|
||||
this.bytesToBacktrack = 4;
|
||||
this.offset += this.bytesToBacktrack;
|
||||
return value;
|
||||
}
|
||||
|
||||
writeUInt32(value: number): void {
|
||||
this.dump(`u32(${value})`);
|
||||
this.buffer.writeUInt32LE(value, this.offset);
|
||||
this.offset += 4;
|
||||
}
|
||||
|
||||
readCompactLength(): number {
|
||||
let length = this.readUInt8();
|
||||
if (length === UhkBuffer.longCompactLengthPrefix) {
|
||||
length += this.readUInt8() << 8;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
writeCompactLength(length: number) {
|
||||
if (length >= UhkBuffer.longCompactLengthPrefix) {
|
||||
this.writeUInt8(UhkBuffer.longCompactLengthPrefix);
|
||||
this.writeUInt16(length);
|
||||
} else {
|
||||
this.writeUInt8(length);
|
||||
}
|
||||
}
|
||||
|
||||
readString(): string {
|
||||
let stringByteLength = this.readCompactLength();
|
||||
let str = this.buffer.toString(UhkBuffer.stringEncoding, this.offset, this.offset + stringByteLength);
|
||||
this.dump(`${UhkBuffer.stringEncoding}(${str})`);
|
||||
this.bytesToBacktrack = stringByteLength;
|
||||
this.offset += stringByteLength;
|
||||
return str;
|
||||
}
|
||||
|
||||
writeString(str: string): void {
|
||||
let stringByteLength = Buffer.byteLength(str, UhkBuffer.stringEncoding);
|
||||
|
||||
if (stringByteLength > UhkBuffer.maxCompactLength) {
|
||||
throw 'Cannot serialize string: ${stringByteLength} bytes is larger ' +
|
||||
'than the maximum allowed length of ${UhkBuffer.maxStringByteLength} bytes';
|
||||
}
|
||||
|
||||
this.writeCompactLength(stringByteLength);
|
||||
this.dump(`${UhkBuffer.stringEncoding}(${str})`);
|
||||
this.buffer.write(str, this.offset, stringByteLength, UhkBuffer.stringEncoding);
|
||||
this.offset += stringByteLength;
|
||||
}
|
||||
|
||||
readBoolean(): boolean {
|
||||
return this.readUInt8() !== 0;
|
||||
}
|
||||
|
||||
writeBoolean(bool: boolean) {
|
||||
this.writeUInt8(bool ? 1 : 0);
|
||||
}
|
||||
|
||||
backtrack(): void {
|
||||
this.offset -= this.bytesToBacktrack;
|
||||
this.bytesToBacktrack = 0;
|
||||
}
|
||||
|
||||
getBufferContent(): Buffer {
|
||||
return this.buffer.slice(0, this.offset);
|
||||
}
|
||||
|
||||
get enableDump() {
|
||||
return this._enableDump;
|
||||
}
|
||||
|
||||
set enableDump(value) {
|
||||
if (value) {
|
||||
UhkBuffer.isFirstElementToDump = true;
|
||||
}
|
||||
this._enableDump = value;
|
||||
}
|
||||
|
||||
dump(value: any) {
|
||||
if (!this.enableDump) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UhkBuffer.isFirstElementToDump) {
|
||||
process.stdout.write(', ');
|
||||
}
|
||||
|
||||
process.stdout.write(value);
|
||||
|
||||
if (UhkBuffer.isFirstElementToDump) {
|
||||
UhkBuffer.isFirstElementToDump = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
78
src/config-serializer/assert.ts
Normal file
78
src/config-serializer/assert.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
export function assertUInt8(target: any, key: string) {
|
||||
return assertInteger(target, key, 0, 0xFF);
|
||||
}
|
||||
|
||||
export function assertInt8(target: any, key: string) {
|
||||
return assertInteger(target, key, -0x80, 0x7F);
|
||||
}
|
||||
|
||||
export function assertUInt16(target: any, key: string) {
|
||||
return assertInteger(target, key, 0, 0xFFFF);
|
||||
}
|
||||
|
||||
export function assertInt16(target: any, key: string) {
|
||||
return assertInteger(target, key, -0x8000, 0x7FFF);
|
||||
}
|
||||
|
||||
export function assertUInt32(target: any, key: string) {
|
||||
return assertInteger(target, key, 0, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
export function assertInt32(target: any, key: string) {
|
||||
return assertInteger(target, key, -0x80000000, 0x7FFFFFFF);
|
||||
}
|
||||
|
||||
export function assertCompactLength(target: any, key: string) {
|
||||
return assertUInt16(target, key);
|
||||
}
|
||||
|
||||
function assertInteger(target: any, key: string, min: number, max: number) {
|
||||
const priv = '_' + key;
|
||||
|
||||
function getter() {
|
||||
return this[priv];
|
||||
}
|
||||
|
||||
function setter(newVal: any) {
|
||||
if (this[priv] !== newVal) {
|
||||
if (newVal < min || newVal > max) {
|
||||
throw `${target.constructor.name}.${key}: ` +
|
||||
`Integer ${newVal} is outside the valid [${min}, ${max}] interval`;
|
||||
}
|
||||
this[priv] = newVal;
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(target, key, {
|
||||
get: getter,
|
||||
set: setter,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
|
||||
export function assertEnum<E>(enumerated: E) {
|
||||
return function(target: any, key: string) {
|
||||
const priv = '_' + key;
|
||||
|
||||
function getter() {
|
||||
return this[priv];
|
||||
}
|
||||
|
||||
function setter(newVal: any) {
|
||||
if (this[priv] !== newVal) {
|
||||
if (enumerated[newVal] === undefined) {
|
||||
throw `${target.constructor.name}.${key}: ${newVal} is not enum`;
|
||||
}
|
||||
this[priv] = newVal;
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(target, key, {
|
||||
get: getter,
|
||||
set: setter,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
};
|
||||
}
|
||||
37
src/config-serializer/config-items/DelayMacroAction.ts
Normal file
37
src/config-serializer/config-items/DelayMacroAction.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {MacroAction, macroActionType, MacroActionId} from './MacroAction';
|
||||
import {assertUInt16} from '../assert';
|
||||
|
||||
export class DelayMacroAction extends MacroAction {
|
||||
|
||||
@assertUInt16
|
||||
delay: number;
|
||||
|
||||
_fromJsObject(jsObject: any): DelayMacroAction {
|
||||
this.assertMacroActionType(jsObject);
|
||||
this.delay = jsObject.delay;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): DelayMacroAction {
|
||||
this.readAndAssertMacroActionId(buffer);
|
||||
this.delay = buffer.readUInt16();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
macroActionType: macroActionType.DelayMacroAction,
|
||||
delay: this.delay
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(MacroActionId.DelayMacroAction);
|
||||
buffer.writeUInt16(this.delay);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<DelayMacroAction delay="${this.delay}">`;
|
||||
}
|
||||
}
|
||||
37
src/config-serializer/config-items/HoldKeyMacroAction.ts
Normal file
37
src/config-serializer/config-items/HoldKeyMacroAction.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {MacroAction, MacroActionId, macroActionType} from './MacroAction';
|
||||
import {assertUInt8} from '../assert';
|
||||
|
||||
export class HoldKeyMacroAction extends MacroAction {
|
||||
|
||||
@assertUInt8
|
||||
scancode: number;
|
||||
|
||||
_fromJsObject(jsObject: any): HoldKeyMacroAction {
|
||||
this.assertMacroActionType(jsObject);
|
||||
this.scancode = jsObject.scancode;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): HoldKeyMacroAction {
|
||||
this.readAndAssertMacroActionId(buffer);
|
||||
this.scancode = buffer.readUInt8();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
macroActionType: macroActionType.HoldKeyMacroAction,
|
||||
scancode: this.scancode
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(MacroActionId.HoldKeyMacroAction);
|
||||
buffer.writeUInt8(this.scancode);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<HoldKeyMacroAction scancode="${this.scancode}">`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import {MacroAction, MacroActionId, macroActionType} from './MacroAction';
|
||||
import {KeyModifiers} from './KeyModifiers';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertUInt8} from '../assert';
|
||||
|
||||
export class HoldModifiersMacroAction extends MacroAction {
|
||||
|
||||
@assertUInt8
|
||||
modifierMask: number;
|
||||
|
||||
_fromJsObject(jsObject: any): HoldModifiersMacroAction {
|
||||
this.assertMacroActionType(jsObject);
|
||||
this.modifierMask = jsObject.modifierMask;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): HoldModifiersMacroAction {
|
||||
this.readAndAssertMacroActionId(buffer);
|
||||
this.modifierMask = buffer.readUInt8();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
macroActionType: macroActionType.HoldModifiersMacroAction,
|
||||
modifierMask: this.modifierMask
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(MacroActionId.HoldModifiersMacroAction);
|
||||
buffer.writeUInt8(this.modifierMask);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<HoldModifiersMacroAction modifierMask="${this.modifierMask}">`;
|
||||
}
|
||||
|
||||
isModifierActive(modifier: KeyModifiers): boolean {
|
||||
return (this.modifierMask & modifier) > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {MacroAction, MacroActionId, macroActionType} from './MacroAction';
|
||||
import {assertUInt8} from '../assert';
|
||||
|
||||
export class HoldMouseButtonsMacroAction extends MacroAction {
|
||||
|
||||
@assertUInt8
|
||||
mouseButtonsMask: number;
|
||||
|
||||
_fromJsObject(jsObject: any): HoldMouseButtonsMacroAction {
|
||||
this.assertMacroActionType(jsObject);
|
||||
this.mouseButtonsMask = jsObject.mouseButtonsMask;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): HoldMouseButtonsMacroAction {
|
||||
this.readAndAssertMacroActionId(buffer);
|
||||
this.mouseButtonsMask = buffer.readUInt8();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
macroActionType: macroActionType.HoldMouseButtonsMacroAction,
|
||||
mouseButtonsMask: this.mouseButtonsMask
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(MacroActionId.HoldMouseButtonsMacroAction);
|
||||
buffer.writeUInt8(this.mouseButtonsMask);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<HoldMouseButtonsMacroAction mouseButtonsMask="${this.mouseButtonsMask}">`;
|
||||
}
|
||||
}
|
||||
60
src/config-serializer/config-items/KeyAction.ts
Normal file
60
src/config-serializer/config-items/KeyAction.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
/// <reference path="../Function.d.ts" />
|
||||
|
||||
import {Serializable} from '../Serializable';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
|
||||
export enum KeyActionId {
|
||||
NoneAction = 0,
|
||||
KeystrokeAction = 1,
|
||||
/*
|
||||
1 - 7 are reserved for KeystrokeAction
|
||||
3 bits:
|
||||
1: Do we have scancode?
|
||||
2: Do we have modifiers?
|
||||
3: Do we have longpress?
|
||||
*/
|
||||
LastKeystrokeAction = 7, // TODO: remove this after refactoring the keyActionId check
|
||||
SwitchLayerAction = 8,
|
||||
SwitchKeymapAction = 9,
|
||||
MouseAction = 10,
|
||||
PlayMacroAction = 11
|
||||
}
|
||||
|
||||
export let keyActionType = {
|
||||
NoneAction : 'none',
|
||||
KeystrokeAction : 'keystroke',
|
||||
SwitchLayerAction : 'switchLayer',
|
||||
SwitchKeymapAction : 'switchKeymap',
|
||||
MouseAction : 'mouse',
|
||||
PlayMacroAction : 'playMacro'
|
||||
};
|
||||
|
||||
export abstract class KeyAction extends Serializable<KeyAction> {
|
||||
|
||||
assertKeyActionType(jsObject: any): void {
|
||||
let keyActionClassname: string = this.constructor.name;
|
||||
let keyActionTypeString: string = keyActionType[keyActionClassname];
|
||||
if (jsObject.keyActionType !== keyActionTypeString) {
|
||||
throw `Invalid ${keyActionClassname}.keyActionType: ${jsObject.keyActionType}`;
|
||||
}
|
||||
}
|
||||
|
||||
readAndAssertKeyActionId(buffer: UhkBuffer): KeyActionId {
|
||||
let classname: string = this.constructor.name;
|
||||
let readKeyActionId: number = buffer.readUInt8();
|
||||
let keyActionId: number = KeyActionId[classname];
|
||||
if (keyActionId === KeyActionId.KeystrokeAction) {
|
||||
if (readKeyActionId < KeyActionId.KeystrokeAction || readKeyActionId > KeyActionId.LastKeystrokeAction) {
|
||||
throw `Invalid ${classname} first byte: ${readKeyActionId}`;
|
||||
}
|
||||
} else if (readKeyActionId !== keyActionId) {
|
||||
throw `Invalid ${classname} first byte: ${readKeyActionId}`;
|
||||
}
|
||||
return readKeyActionId;
|
||||
}
|
||||
|
||||
abstract _fromJsObject(jsObject: any): KeyAction;
|
||||
abstract _fromBinary(buffer: UhkBuffer): KeyAction;
|
||||
abstract _toJsObject(): any;
|
||||
abstract _toBinary(buffer: UhkBuffer): void;
|
||||
}
|
||||
60
src/config-serializer/config-items/KeyActions.ts
Normal file
60
src/config-serializer/config-items/KeyActions.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import {ClassArray} from '../ClassArray';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {NoneAction} from './NoneAction';
|
||||
import {KeystrokeAction} from './KeystrokeAction';
|
||||
import {keyActionType, KeyActionId, KeyAction} from './KeyAction';
|
||||
import {SwitchLayerAction} from './SwitchLayerAction';
|
||||
import {SwitchKeymapAction} from './SwitchKeymapAction';
|
||||
import {MouseAction} from './MouseAction';
|
||||
import {PlayMacroAction} from './PlayMacroAction';
|
||||
|
||||
export class KeyActions extends ClassArray<KeyAction> {
|
||||
|
||||
jsObjectToClass(jsObject: any): KeyAction {
|
||||
switch (jsObject.keyActionType) {
|
||||
case keyActionType.NoneAction:
|
||||
return new NoneAction().fromJsObject(jsObject);
|
||||
case keyActionType.KeystrokeAction:
|
||||
return new KeystrokeAction().fromJsObject(jsObject);
|
||||
case keyActionType.SwitchLayerAction:
|
||||
return new SwitchLayerAction().fromJsObject(jsObject);
|
||||
case keyActionType.SwitchKeymapAction:
|
||||
return new SwitchKeymapAction().fromJsObject(jsObject);
|
||||
case keyActionType.MouseAction:
|
||||
return new MouseAction().fromJsObject(jsObject);
|
||||
case keyActionType.PlayMacroAction:
|
||||
return new PlayMacroAction().fromJsObject(jsObject);
|
||||
default:
|
||||
throw `Invalid KeyAction.keyActionType: "${jsObject.keyActionType}"`;
|
||||
}
|
||||
}
|
||||
|
||||
binaryToClass(buffer: UhkBuffer): KeyAction {
|
||||
let keyActionFirstByte = buffer.readUInt8();
|
||||
buffer.backtrack();
|
||||
|
||||
if (buffer.enableDump) {
|
||||
process.stdout.write(']\n');
|
||||
buffer.enableDump = false;
|
||||
}
|
||||
|
||||
if (keyActionFirstByte >= KeyActionId.KeystrokeAction && keyActionFirstByte < KeyActionId.LastKeystrokeAction) {
|
||||
return new KeystrokeAction().fromBinary(buffer);
|
||||
}
|
||||
|
||||
switch (keyActionFirstByte) {
|
||||
case KeyActionId.NoneAction:
|
||||
return new NoneAction().fromBinary(buffer);
|
||||
case KeyActionId.SwitchLayerAction:
|
||||
return new SwitchLayerAction().fromBinary(buffer);
|
||||
case KeyActionId.SwitchKeymapAction:
|
||||
return new SwitchKeymapAction().fromBinary(buffer);
|
||||
case KeyActionId.MouseAction:
|
||||
return new MouseAction().fromBinary(buffer);
|
||||
case KeyActionId.PlayMacroAction:
|
||||
return new PlayMacroAction().fromBinary(buffer);
|
||||
default:
|
||||
throw `Invalid KeyAction first byte: ${keyActionFirstByte}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/config-serializer/config-items/KeyModifiers.ts
Normal file
10
src/config-serializer/config-items/KeyModifiers.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export enum KeyModifiers {
|
||||
leftCtrl = 1 << 0,
|
||||
leftShift = 1 << 1,
|
||||
leftAlt = 1 << 2,
|
||||
leftGui = 1 << 3,
|
||||
rightCtrl = 1 << 4,
|
||||
rightShift = 1 << 5,
|
||||
rightAlt = 1 << 6,
|
||||
rightGui = 1 << 7
|
||||
}
|
||||
58
src/config-serializer/config-items/Keymap.ts
Normal file
58
src/config-serializer/config-items/Keymap.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import {Serializable} from '../Serializable';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {Layers} from './Layers';
|
||||
import {assertUInt8} from '../assert';
|
||||
|
||||
export class Keymap extends Serializable<Keymap> {
|
||||
|
||||
@assertUInt8
|
||||
id: number;
|
||||
|
||||
name: string;
|
||||
|
||||
abbreviation: string;
|
||||
|
||||
isDefault: boolean;
|
||||
|
||||
layers: Layers;
|
||||
|
||||
_fromJsObject(jsObject: any): Keymap {
|
||||
this.id = jsObject.id;
|
||||
this.isDefault = jsObject.isDefault;
|
||||
this.abbreviation = jsObject.abbreviation;
|
||||
this.name = jsObject.name;
|
||||
this.layers = new Layers().fromJsObject(jsObject.layers);
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): Keymap {
|
||||
this.id = buffer.readUInt8();
|
||||
this.isDefault = buffer.readBoolean();
|
||||
this.abbreviation = buffer.readString();
|
||||
this.name = buffer.readString();
|
||||
this.layers = new Layers().fromBinary(buffer);
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
id: this.id,
|
||||
isDefault: this.isDefault,
|
||||
abbreviation: this.abbreviation,
|
||||
name: this.name,
|
||||
layers: this.layers.toJsObject()
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer): void {
|
||||
buffer.writeUInt8(this.id);
|
||||
buffer.writeBoolean(this.isDefault);
|
||||
buffer.writeString(this.abbreviation);
|
||||
buffer.writeString(this.name);
|
||||
this.layers.toBinary(buffer);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<Keymap id="${this.id}" name="${this.name}">`;
|
||||
}
|
||||
}
|
||||
15
src/config-serializer/config-items/Keymaps.ts
Normal file
15
src/config-serializer/config-items/Keymaps.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import {ClassArray} from '../ClassArray';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {Keymap} from './Keymap';
|
||||
|
||||
export class Keymaps extends ClassArray<Keymap> {
|
||||
|
||||
jsObjectToClass(jsObject: any): Keymap {
|
||||
return new Keymap().fromJsObject(jsObject);
|
||||
}
|
||||
|
||||
binaryToClass(buffer: UhkBuffer): Keymap {
|
||||
return new Keymap().fromBinary(buffer);
|
||||
}
|
||||
|
||||
}
|
||||
133
src/config-serializer/config-items/KeystrokeAction.ts
Normal file
133
src/config-serializer/config-items/KeystrokeAction.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {keyActionType, KeyActionId, KeyAction} from './KeyAction';
|
||||
import {KeyModifiers} from './KeyModifiers';
|
||||
import {assertUInt8, assertEnum} from '../assert';
|
||||
import {LongPressAction} from './LongPressAction';
|
||||
|
||||
export enum KeystrokeActionFlag {
|
||||
scancode = 1 << 0,
|
||||
modifierMask = 1 << 1,
|
||||
longPressAction = 1 << 2,
|
||||
}
|
||||
|
||||
interface JsObjectKeystrokeAction {
|
||||
keyActionType: string;
|
||||
scancode?: number;
|
||||
modifierMask?: number;
|
||||
longPressAction?: string;
|
||||
}
|
||||
|
||||
export class KeystrokeAction extends KeyAction {
|
||||
|
||||
@assertUInt8
|
||||
scancode: number;
|
||||
|
||||
@assertUInt8
|
||||
modifierMask: number;
|
||||
|
||||
@assertEnum(LongPressAction)
|
||||
longPressAction: LongPressAction;
|
||||
|
||||
_fromJsObject(jsObject: JsObjectKeystrokeAction): KeystrokeAction {
|
||||
this.assertKeyActionType(jsObject);
|
||||
this.scancode = jsObject.scancode;
|
||||
this.modifierMask = jsObject.modifierMask;
|
||||
this.longPressAction = LongPressAction[jsObject.longPressAction];
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): KeystrokeAction {
|
||||
let keyActionId: KeyActionId = this.readAndAssertKeyActionId(buffer);
|
||||
let flags: number = keyActionId - KeyActionId.KeystrokeAction;
|
||||
if (flags & KeystrokeActionFlag.scancode) {
|
||||
this.scancode = buffer.readUInt8();
|
||||
}
|
||||
if (flags & KeystrokeActionFlag.modifierMask) {
|
||||
this.modifierMask = buffer.readUInt8();
|
||||
}
|
||||
if (flags & KeystrokeActionFlag.longPressAction) {
|
||||
this.longPressAction = buffer.readUInt8();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): JsObjectKeystrokeAction {
|
||||
let jsObject: JsObjectKeystrokeAction = {
|
||||
keyActionType: keyActionType.KeystrokeAction
|
||||
};
|
||||
|
||||
if (this.hasScancode()) {
|
||||
jsObject.scancode = this.scancode;
|
||||
}
|
||||
|
||||
if (this.hasActiveModifier()) {
|
||||
jsObject.modifierMask = this.modifierMask;
|
||||
}
|
||||
|
||||
if (this.hasLongPressAction()) {
|
||||
jsObject.longPressAction = LongPressAction[this.longPressAction];
|
||||
}
|
||||
|
||||
return jsObject;
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
let flags = 0;
|
||||
let bufferData: number[] = [];
|
||||
|
||||
if (this.hasScancode()) {
|
||||
flags |= KeystrokeActionFlag.scancode;
|
||||
bufferData.push(this.scancode);
|
||||
}
|
||||
|
||||
if (this.hasActiveModifier()) {
|
||||
flags |= KeystrokeActionFlag.modifierMask;
|
||||
bufferData.push(this.modifierMask);
|
||||
}
|
||||
|
||||
if (this.hasLongPressAction()) {
|
||||
flags |= KeystrokeActionFlag.longPressAction;
|
||||
bufferData.push(this.longPressAction);
|
||||
}
|
||||
|
||||
buffer.writeUInt8(KeyActionId.KeystrokeAction + flags);
|
||||
for (let i = 0; i < bufferData.length; ++i) {
|
||||
buffer.writeUInt8(bufferData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
let properties: string[] = [];
|
||||
if (this.hasScancode()) {
|
||||
properties.push(`scancode="${this.scancode}"`);
|
||||
}
|
||||
if (this.hasActiveModifier()) {
|
||||
properties.push(`modifierMask="${this.modifierMask}"`);
|
||||
}
|
||||
if (this.hasLongPressAction()) {
|
||||
properties.push(`longPressAction="${this.longPressAction}"`);
|
||||
}
|
||||
|
||||
return `<KeystrokeAction ${properties.join(' ')}>`;
|
||||
}
|
||||
|
||||
isActive(modifier: KeyModifiers): boolean {
|
||||
return (this.modifierMask & modifier) > 0;
|
||||
}
|
||||
|
||||
hasActiveModifier(): boolean {
|
||||
return this.modifierMask > 0;
|
||||
}
|
||||
|
||||
hasLongPressAction(): boolean {
|
||||
return this.longPressAction !== undefined;
|
||||
}
|
||||
|
||||
hasScancode(): boolean {
|
||||
return !!this.scancode;
|
||||
}
|
||||
|
||||
hasOnlyOneActiveModifier(): boolean {
|
||||
return this.modifierMask !== 0 && !(this.modifierMask & this.modifierMask - 1);
|
||||
}
|
||||
}
|
||||
35
src/config-serializer/config-items/Layer.ts
Normal file
35
src/config-serializer/config-items/Layer.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Serializable } from '../Serializable';
|
||||
import { Modules } from './Modules';
|
||||
import { UhkBuffer } from '../UhkBuffer';
|
||||
import { AnimationKeyboard } from '../../components/svg/wrap';
|
||||
|
||||
export class Layer extends Serializable<Layer> {
|
||||
|
||||
modules: Modules;
|
||||
animation: AnimationKeyboard = 'none';
|
||||
|
||||
_fromJsObject(jsObject: any): Layer {
|
||||
this.modules = new Modules().fromJsObject(jsObject.modules);
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): Layer {
|
||||
this.modules = new Modules().fromBinary(buffer);
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
modules: this.modules.toJsObject()
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer): void {
|
||||
this.modules.toBinary(buffer);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<Layer>`;
|
||||
}
|
||||
|
||||
}
|
||||
15
src/config-serializer/config-items/Layers.ts
Normal file
15
src/config-serializer/config-items/Layers.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import {ClassArray} from '../ClassArray';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {Layer} from './Layer';
|
||||
|
||||
export class Layers extends ClassArray<Layer> {
|
||||
|
||||
jsObjectToClass(jsObject: any): Layer {
|
||||
return new Layer().fromJsObject(jsObject);
|
||||
}
|
||||
|
||||
binaryToClass(buffer: UhkBuffer): Layer {
|
||||
return new Layer().fromBinary(buffer);
|
||||
}
|
||||
|
||||
}
|
||||
13
src/config-serializer/config-items/LongPressAction.ts
Normal file
13
src/config-serializer/config-items/LongPressAction.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export enum LongPressAction {
|
||||
leftCtrl,
|
||||
leftShift,
|
||||
leftAlt,
|
||||
leftSuper,
|
||||
rightCtrl,
|
||||
rightShift,
|
||||
rightAlt,
|
||||
rightSuper,
|
||||
mod,
|
||||
fn,
|
||||
mouse
|
||||
};
|
||||
58
src/config-serializer/config-items/Macro.ts
Normal file
58
src/config-serializer/config-items/Macro.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import {Serializable} from '../Serializable';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {MacroActions} from './MacroActions';
|
||||
import {assertUInt8} from '../assert';
|
||||
|
||||
export class Macro extends Serializable<Macro> {
|
||||
|
||||
@assertUInt8
|
||||
id: number;
|
||||
|
||||
isLooped: boolean;
|
||||
|
||||
isPrivate: boolean;
|
||||
|
||||
name: string;
|
||||
|
||||
macroActions: MacroActions;
|
||||
|
||||
_fromJsObject(jsObject: any): Macro {
|
||||
this.id = jsObject.id;
|
||||
this.isLooped = jsObject.isLooped;
|
||||
this.isPrivate = jsObject.isPrivate;
|
||||
this.name = jsObject.name;
|
||||
this.macroActions = new MacroActions().fromJsObject(jsObject.macroActions);
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): Macro {
|
||||
this.id = buffer.readUInt8();
|
||||
this.isLooped = buffer.readBoolean();
|
||||
this.isPrivate = buffer.readBoolean();
|
||||
this.name = buffer.readString();
|
||||
this.macroActions = new MacroActions().fromBinary(buffer);
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
id: this.id,
|
||||
isLooped: this.isLooped,
|
||||
isPrivate: this.isPrivate,
|
||||
name: this.name,
|
||||
macroActions: this.macroActions.toJsObject()
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer): void {
|
||||
buffer.writeUInt8(this.id);
|
||||
buffer.writeBoolean(this.isLooped);
|
||||
buffer.writeBoolean(this.isPrivate);
|
||||
buffer.writeString(this.name);
|
||||
this.macroActions.toBinary(buffer);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<Macro id="${this.id}" name="${this.name}">`;
|
||||
}
|
||||
}
|
||||
58
src/config-serializer/config-items/MacroAction.ts
Normal file
58
src/config-serializer/config-items/MacroAction.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import {Serializable} from '../Serializable';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
|
||||
export enum MacroActionId {
|
||||
PressKeyMacroAction = 0,
|
||||
HoldKeyMacroAction = 1,
|
||||
ReleaseKeyMacroAction = 2,
|
||||
PressModifiersMacroAction = 3,
|
||||
HoldModifiersMacroAction = 4,
|
||||
ReleaseModifiersMacroAction = 5,
|
||||
PressMouseButtonsMacroAction = 6,
|
||||
HoldMouseButtonsMacroAction = 7,
|
||||
ReleaseMouseButtonsMacroAction = 8,
|
||||
MoveMouseMacroAction = 9,
|
||||
ScrollMouseMacroAction = 10,
|
||||
DelayMacroAction = 11,
|
||||
TextMacroAction = 12
|
||||
}
|
||||
|
||||
export let macroActionType = {
|
||||
PressKeyMacroAction : 'pressKey',
|
||||
HoldKeyMacroAction : 'holdKey',
|
||||
ReleaseKeyMacroAction : 'releaseKey',
|
||||
PressModifiersMacroAction : 'pressModifiers',
|
||||
HoldModifiersMacroAction : 'holdModifiers',
|
||||
ReleaseModifiersMacroAction : 'releaseModifiers',
|
||||
PressMouseButtonsMacroAction : 'pressMouseButtons',
|
||||
HoldMouseButtonsMacroAction : 'holdMouseButtons',
|
||||
ReleaseMouseButtonsMacroAction : 'releaseMouseButtons',
|
||||
MoveMouseMacroAction : 'moveMouse',
|
||||
ScrollMouseMacroAction : 'scrollMouse',
|
||||
DelayMacroAction : 'delay',
|
||||
TextMacroAction : 'text'
|
||||
};
|
||||
|
||||
export abstract class MacroAction extends Serializable<MacroAction> {
|
||||
assertMacroActionType(jsObject: any) {
|
||||
let macroActionClassname = this.constructor.name;
|
||||
let macroActionTypeString = macroActionType[macroActionClassname];
|
||||
if (jsObject.macroActionType !== macroActionTypeString) {
|
||||
throw `Invalid ${macroActionClassname}.macroActionType: ${jsObject.macroActionType}`;
|
||||
}
|
||||
}
|
||||
|
||||
readAndAssertMacroActionId(buffer: UhkBuffer) {
|
||||
let classname = this.constructor.name;
|
||||
let readMacroActionId = buffer.readUInt8();
|
||||
let macroActionId = MacroActionId[<string> classname];
|
||||
if (readMacroActionId !== macroActionId) {
|
||||
throw `Invalid ${classname} first byte: ${readMacroActionId}`;
|
||||
}
|
||||
}
|
||||
|
||||
abstract _fromJsObject(jsObject: any): MacroAction;
|
||||
abstract _fromBinary(buffer: UhkBuffer): MacroAction;
|
||||
abstract _toJsObject(): any;
|
||||
abstract _toBinary(buffer: UhkBuffer): void;
|
||||
}
|
||||
93
src/config-serializer/config-items/MacroActions.ts
Normal file
93
src/config-serializer/config-items/MacroActions.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import {ClassArray} from '../ClassArray';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {DelayMacroAction} from './DelayMacroAction';
|
||||
import {MacroAction, macroActionType, MacroActionId} from './MacroAction';
|
||||
import {HoldKeyMacroAction} from './HoldKeyMacroAction';
|
||||
import {HoldModifiersMacroAction} from './HoldModifiersMacroAction';
|
||||
import {HoldMouseButtonsMacroAction} from './HoldMouseButtonsMacroAction';
|
||||
import {MoveMouseMacroAction} from './MoveMouseMacroAction';
|
||||
import {PressKeyMacroAction} from './PressKeyMacroAction';
|
||||
import {PressModifiersMacroAction} from './PressModifiersMacroAction';
|
||||
import {PressMouseButtonsMacroAction} from './PressMouseButtonsMacroAction';
|
||||
import {ReleaseKeyMacroAction} from './ReleaseKeyMacroAction';
|
||||
import {ReleaseModifiersMacroAction} from './ReleaseModifiersMacroAction';
|
||||
import {ReleaseMouseButtonsMacroAction} from './ReleaseMouseButtonsMacroAction';
|
||||
import {ScrollMouseMacroAction} from './ScrollMouseMacroAction';
|
||||
import {TextMacroAction} from './TextMacroAction';
|
||||
|
||||
export class MacroActions extends ClassArray<MacroAction> {
|
||||
|
||||
jsObjectToClass(jsObject: any): MacroAction {
|
||||
switch (jsObject.macroActionType) {
|
||||
case macroActionType.PressKeyMacroAction:
|
||||
return new PressKeyMacroAction().fromJsObject(jsObject);
|
||||
case macroActionType.HoldKeyMacroAction:
|
||||
return new HoldKeyMacroAction().fromJsObject(jsObject);
|
||||
case macroActionType.ReleaseKeyMacroAction:
|
||||
return new ReleaseKeyMacroAction().fromJsObject(jsObject);
|
||||
case macroActionType.PressModifiersMacroAction:
|
||||
return new PressModifiersMacroAction().fromJsObject(jsObject);
|
||||
case macroActionType.HoldModifiersMacroAction:
|
||||
return new HoldModifiersMacroAction().fromJsObject(jsObject);
|
||||
case macroActionType.ReleaseModifiersMacroAction:
|
||||
return new ReleaseModifiersMacroAction().fromJsObject(jsObject);
|
||||
case macroActionType.PressMouseButtonsMacroAction:
|
||||
return new PressMouseButtonsMacroAction().fromJsObject(jsObject);
|
||||
case macroActionType.HoldMouseButtonsMacroAction:
|
||||
return new HoldMouseButtonsMacroAction().fromJsObject(jsObject);
|
||||
case macroActionType.ReleaseMouseButtonsMacroAction:
|
||||
return new ReleaseMouseButtonsMacroAction().fromJsObject(jsObject);
|
||||
case macroActionType.MoveMouseMacroAction:
|
||||
return new MoveMouseMacroAction().fromJsObject(jsObject);
|
||||
case macroActionType.ScrollMouseMacroAction:
|
||||
return new ScrollMouseMacroAction().fromJsObject(jsObject);
|
||||
case macroActionType.DelayMacroAction:
|
||||
return new DelayMacroAction().fromJsObject(jsObject);
|
||||
case macroActionType.TextMacroAction:
|
||||
return new TextMacroAction().fromJsObject(jsObject);
|
||||
default:
|
||||
throw `Invalid MacroAction.macroActionType: "${jsObject.macroActionType}"`;
|
||||
}
|
||||
}
|
||||
|
||||
binaryToClass(buffer: UhkBuffer): MacroAction {
|
||||
let macroActionFirstByte = buffer.readUInt8();
|
||||
buffer.backtrack();
|
||||
|
||||
if (buffer.enableDump) {
|
||||
process.stdout.write(']\n');
|
||||
buffer.enableDump = false;
|
||||
}
|
||||
|
||||
switch (macroActionFirstByte) {
|
||||
case MacroActionId.PressKeyMacroAction:
|
||||
return new PressKeyMacroAction().fromBinary(buffer);
|
||||
case MacroActionId.HoldKeyMacroAction:
|
||||
return new HoldKeyMacroAction().fromBinary(buffer);
|
||||
case MacroActionId.ReleaseKeyMacroAction:
|
||||
return new ReleaseKeyMacroAction().fromBinary(buffer);
|
||||
case MacroActionId.PressModifiersMacroAction:
|
||||
return new PressModifiersMacroAction().fromBinary(buffer);
|
||||
case MacroActionId.HoldModifiersMacroAction:
|
||||
return new HoldModifiersMacroAction().fromBinary(buffer);
|
||||
case MacroActionId.ReleaseModifiersMacroAction:
|
||||
return new ReleaseModifiersMacroAction().fromBinary(buffer);
|
||||
case MacroActionId.PressMouseButtonsMacroAction:
|
||||
return new PressMouseButtonsMacroAction().fromBinary(buffer);
|
||||
case MacroActionId.HoldMouseButtonsMacroAction:
|
||||
return new HoldMouseButtonsMacroAction().fromBinary(buffer);
|
||||
case MacroActionId.ReleaseMouseButtonsMacroAction:
|
||||
return new ReleaseMouseButtonsMacroAction().fromBinary(buffer);
|
||||
case MacroActionId.MoveMouseMacroAction:
|
||||
return new MoveMouseMacroAction().fromBinary(buffer);
|
||||
case MacroActionId.ScrollMouseMacroAction:
|
||||
return new ScrollMouseMacroAction().fromBinary(buffer);
|
||||
case MacroActionId.DelayMacroAction:
|
||||
return new DelayMacroAction().fromBinary(buffer);
|
||||
case MacroActionId.TextMacroAction:
|
||||
return new TextMacroAction().fromBinary(buffer);
|
||||
default:
|
||||
throw `Invalid MacroAction first byte: ${macroActionFirstByte}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/config-serializer/config-items/Macros.ts
Normal file
15
src/config-serializer/config-items/Macros.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import {ClassArray} from '../ClassArray';
|
||||
import {Macro} from './Macro';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
|
||||
export class Macros extends ClassArray<Macro> {
|
||||
|
||||
jsObjectToClass(jsObject: any): Macro {
|
||||
return new Macro().fromJsObject(jsObject);
|
||||
}
|
||||
|
||||
binaryToClass(buffer: UhkBuffer): Macro {
|
||||
return new Macro().fromBinary(buffer);
|
||||
}
|
||||
|
||||
}
|
||||
54
src/config-serializer/config-items/Module.ts
Normal file
54
src/config-serializer/config-items/Module.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import {Serializable} from '../Serializable';
|
||||
import {KeyActions} from './KeyActions';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertUInt8, assertEnum} from '../assert';
|
||||
|
||||
enum PointerRole {
|
||||
none,
|
||||
move,
|
||||
scroll
|
||||
}
|
||||
|
||||
export class Module extends Serializable<Module> {
|
||||
|
||||
@assertUInt8
|
||||
id: number;
|
||||
|
||||
keyActions: KeyActions;
|
||||
|
||||
@assertEnum(PointerRole)
|
||||
private pointerRole: PointerRole;
|
||||
|
||||
_fromJsObject(jsObject: any): Module {
|
||||
this.id = jsObject.id;
|
||||
this.pointerRole = PointerRole[<string> jsObject.pointerRole];
|
||||
this.keyActions = new KeyActions().fromJsObject(jsObject.keyActions);
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): Module {
|
||||
this.id = buffer.readUInt8();
|
||||
this.pointerRole = buffer.readUInt8();
|
||||
this.keyActions = new KeyActions().fromBinary(buffer);
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
id: this.id,
|
||||
pointerRole: PointerRole[this.pointerRole],
|
||||
keyActions: this.keyActions.toJsObject()
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer): void {
|
||||
buffer.writeUInt8(this.id);
|
||||
buffer.writeUInt8(this.pointerRole);
|
||||
this.keyActions.toBinary(buffer);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<Module id="${this.id}" pointerRole="${this.pointerRole}">`;
|
||||
}
|
||||
|
||||
}
|
||||
59
src/config-serializer/config-items/ModuleConfiguration.ts
Normal file
59
src/config-serializer/config-items/ModuleConfiguration.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import {Serializable} from '../Serializable';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertUInt8} from '../assert';
|
||||
|
||||
export class ModuleConfiguration extends Serializable<ModuleConfiguration> {
|
||||
|
||||
/*
|
||||
* module id enumeration is a separate story
|
||||
*/
|
||||
|
||||
@assertUInt8
|
||||
id: number;
|
||||
|
||||
@assertUInt8
|
||||
initialPointerSpeed: number;
|
||||
|
||||
@assertUInt8
|
||||
pointerAcceleration: number;
|
||||
|
||||
@assertUInt8
|
||||
maxPointerSpeed: number;
|
||||
|
||||
_fromJsObject(jsObject: any): ModuleConfiguration {
|
||||
this.id = jsObject.id;
|
||||
this.initialPointerSpeed = jsObject.initialPointerSpeed;
|
||||
this.pointerAcceleration = jsObject.pointerAcceleration;
|
||||
this.maxPointerSpeed = jsObject.maxPointerSpeed;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): ModuleConfiguration {
|
||||
this.id = buffer.readUInt8();
|
||||
this.initialPointerSpeed = buffer.readUInt8();
|
||||
this.pointerAcceleration = buffer.readUInt8();
|
||||
this.maxPointerSpeed = buffer.readUInt8();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
id: this.id,
|
||||
initialPointerSpeed: this.initialPointerSpeed,
|
||||
pointerAcceleration: this.pointerAcceleration,
|
||||
maxPointerSpeed: this.maxPointerSpeed
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer): void {
|
||||
buffer.writeUInt8(this.id);
|
||||
buffer.writeUInt8(this.initialPointerSpeed);
|
||||
buffer.writeUInt8(this.pointerAcceleration);
|
||||
buffer.writeUInt8(this.maxPointerSpeed);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<ModuleConfiguration id="${this.id}" >`;
|
||||
}
|
||||
|
||||
}
|
||||
15
src/config-serializer/config-items/ModuleConfigurations.ts
Normal file
15
src/config-serializer/config-items/ModuleConfigurations.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import {ClassArray} from '../ClassArray';
|
||||
import {ModuleConfiguration} from './ModuleConfiguration';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
|
||||
export class ModuleConfigurations extends ClassArray<ModuleConfiguration> {
|
||||
|
||||
jsObjectToClass(jsObject: any): ModuleConfiguration {
|
||||
return new ModuleConfiguration().fromJsObject(jsObject);
|
||||
}
|
||||
|
||||
binaryToClass(buffer: UhkBuffer): ModuleConfiguration {
|
||||
return new ModuleConfiguration().fromBinary(buffer);
|
||||
}
|
||||
|
||||
}
|
||||
15
src/config-serializer/config-items/Modules.ts
Normal file
15
src/config-serializer/config-items/Modules.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import {ClassArray} from '../ClassArray';
|
||||
import {Module} from './Module';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
|
||||
export class Modules extends ClassArray<Module> {
|
||||
|
||||
jsObjectToClass(jsObject: any): Module {
|
||||
return new Module().fromJsObject(jsObject);
|
||||
}
|
||||
|
||||
binaryToClass(buffer: UhkBuffer): Module {
|
||||
return new Module().fromBinary(buffer);
|
||||
}
|
||||
|
||||
}
|
||||
53
src/config-serializer/config-items/MouseAction.ts
Normal file
53
src/config-serializer/config-items/MouseAction.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import {keyActionType, KeyActionId, KeyAction} from './KeyAction';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertEnum} from '../assert';
|
||||
|
||||
export enum MouseActionParam {
|
||||
leftClick,
|
||||
middleClick,
|
||||
rightClick,
|
||||
moveUp,
|
||||
moveDown,
|
||||
moveLeft,
|
||||
moveRight,
|
||||
scrollUp,
|
||||
scrollDown,
|
||||
scrollLeft,
|
||||
scrollRight,
|
||||
accelerate,
|
||||
decelerate
|
||||
}
|
||||
|
||||
export class MouseAction extends KeyAction {
|
||||
|
||||
@assertEnum(MouseActionParam)
|
||||
mouseAction: MouseActionParam;
|
||||
|
||||
_fromJsObject(jsObject: any): MouseAction {
|
||||
this.assertKeyActionType(jsObject);
|
||||
this.mouseAction = MouseActionParam[<string> jsObject.mouseAction];
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): MouseAction {
|
||||
this.readAndAssertKeyActionId(buffer);
|
||||
this.mouseAction = buffer.readUInt8();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
keyActionType: keyActionType.MouseAction,
|
||||
mouseAction: MouseActionParam[this.mouseAction]
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(KeyActionId.MouseAction);
|
||||
buffer.writeUInt8(this.mouseAction);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<MouseAction mouseAction="${this.mouseAction}">`;
|
||||
}
|
||||
}
|
||||
44
src/config-serializer/config-items/MoveMouseMacroAction.ts
Normal file
44
src/config-serializer/config-items/MoveMouseMacroAction.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import {MacroAction, macroActionType, MacroActionId} from './MacroAction';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertInt16} from '../assert';
|
||||
|
||||
export class MoveMouseMacroAction extends MacroAction {
|
||||
|
||||
@assertInt16
|
||||
x: number;
|
||||
|
||||
@assertInt16
|
||||
y: number;
|
||||
|
||||
_fromJsObject(jsObject: any): MoveMouseMacroAction {
|
||||
this.assertMacroActionType(jsObject);
|
||||
this.x = jsObject.x;
|
||||
this.y = jsObject.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): MoveMouseMacroAction {
|
||||
this.readAndAssertMacroActionId(buffer);
|
||||
this.x = buffer.readInt16();
|
||||
this.y = buffer.readInt16();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
macroActionType: macroActionType.MoveMouseMacroAction,
|
||||
x: this.x,
|
||||
y: this.y
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(MacroActionId.MoveMouseMacroAction);
|
||||
buffer.writeInt16(this.x);
|
||||
buffer.writeInt16(this.y);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<MoveMouseMacroAction pos="(${this.x},${this.y})">`;
|
||||
}
|
||||
}
|
||||
29
src/config-serializer/config-items/NoneAction.ts
Normal file
29
src/config-serializer/config-items/NoneAction.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import {keyActionType, KeyActionId, KeyAction} from './KeyAction';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
|
||||
export class NoneAction extends KeyAction {
|
||||
|
||||
_fromJsObject(jsObject: any): NoneAction {
|
||||
this.assertKeyActionType(jsObject);
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): NoneAction {
|
||||
this.readAndAssertKeyActionId(buffer);
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
keyActionType: keyActionType.NoneAction
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(KeyActionId.NoneAction);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return '<NoneAction>';
|
||||
}
|
||||
}
|
||||
37
src/config-serializer/config-items/PlayMacroAction.ts
Normal file
37
src/config-serializer/config-items/PlayMacroAction.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import {keyActionType, KeyActionId, KeyAction} from './KeyAction';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertUInt8} from '../assert';
|
||||
|
||||
export class PlayMacroAction extends KeyAction {
|
||||
|
||||
@assertUInt8
|
||||
macroId: number;
|
||||
|
||||
_fromJsObject(jsObject: any): PlayMacroAction {
|
||||
this.assertKeyActionType(jsObject);
|
||||
this.macroId = jsObject.macroId;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): PlayMacroAction {
|
||||
this.readAndAssertKeyActionId(buffer);
|
||||
this.macroId = buffer.readUInt8();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
keyActionType: keyActionType.PlayMacroAction,
|
||||
macroId: this.macroId
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(KeyActionId.PlayMacroAction);
|
||||
buffer.writeUInt8(this.macroId);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<PlayMacroAction macroId="${this.macroId}">`;
|
||||
}
|
||||
}
|
||||
37
src/config-serializer/config-items/PressKeyMacroAction.ts
Normal file
37
src/config-serializer/config-items/PressKeyMacroAction.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import {MacroAction, MacroActionId, macroActionType} from './MacroAction';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertUInt8} from '../assert';
|
||||
|
||||
export class PressKeyMacroAction extends MacroAction {
|
||||
|
||||
@assertUInt8
|
||||
scancode: number;
|
||||
|
||||
_fromJsObject(jsObject: any): PressKeyMacroAction {
|
||||
this.assertMacroActionType(jsObject);
|
||||
this.scancode = jsObject.scancode;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): PressKeyMacroAction {
|
||||
this.readAndAssertMacroActionId(buffer);
|
||||
this.scancode = buffer.readUInt8();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
macroActionType: macroActionType.PressKeyMacroAction,
|
||||
scancode: this.scancode
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(MacroActionId.PressKeyMacroAction);
|
||||
buffer.writeUInt8(this.scancode);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<PressKeyMacroAction scancode="${this.scancode}">`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import {MacroAction, MacroActionId, macroActionType} from './MacroAction';
|
||||
import {KeyModifiers} from './KeyModifiers';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertUInt8} from '../assert';
|
||||
|
||||
export class PressModifiersMacroAction extends MacroAction {
|
||||
|
||||
@assertUInt8
|
||||
modifierMask: number;
|
||||
|
||||
_fromJsObject(jsObject: any): PressModifiersMacroAction {
|
||||
this.assertMacroActionType(jsObject);
|
||||
this.modifierMask = jsObject.modifierMask;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): PressModifiersMacroAction {
|
||||
this.readAndAssertMacroActionId(buffer);
|
||||
this.modifierMask = buffer.readUInt8();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
macroActionType: macroActionType.PressModifiersMacroAction,
|
||||
modifierMask: this.modifierMask
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(MacroActionId.PressModifiersMacroAction);
|
||||
buffer.writeUInt8(this.modifierMask);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<PressModifiersMacroAction modifierMask="${this.modifierMask}">`;
|
||||
}
|
||||
|
||||
isModifierActive(modifier: KeyModifiers): boolean {
|
||||
return (this.modifierMask & modifier) > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import {MacroAction, MacroActionId, macroActionType} from './MacroAction';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertUInt8} from '../assert';
|
||||
|
||||
export class PressMouseButtonsMacroAction extends MacroAction {
|
||||
|
||||
@assertUInt8
|
||||
mouseButtonsMask: number;
|
||||
|
||||
_fromJsObject(jsObject: any): PressMouseButtonsMacroAction {
|
||||
this.assertMacroActionType(jsObject);
|
||||
this.mouseButtonsMask = jsObject.mouseButtonsMask;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): PressMouseButtonsMacroAction {
|
||||
this.readAndAssertMacroActionId(buffer);
|
||||
this.mouseButtonsMask = buffer.readUInt8();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
macroActionType: macroActionType.PressMouseButtonsMacroAction,
|
||||
mouseButtonsMask: this.mouseButtonsMask
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(MacroActionId.PressMouseButtonsMacroAction);
|
||||
buffer.writeUInt8(this.mouseButtonsMask);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<PressMouseButtonsMacroAction mouseButtonsMask="${this.mouseButtonsMask}">`;
|
||||
}
|
||||
}
|
||||
37
src/config-serializer/config-items/ReleaseKeyMacroAction.ts
Normal file
37
src/config-serializer/config-items/ReleaseKeyMacroAction.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import {MacroAction, MacroActionId, macroActionType} from './MacroAction';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertUInt8} from '../assert';
|
||||
|
||||
export class ReleaseKeyMacroAction extends MacroAction {
|
||||
|
||||
@assertUInt8
|
||||
scancode: number;
|
||||
|
||||
_fromJsObject(jsObject: any): ReleaseKeyMacroAction {
|
||||
this.assertMacroActionType(jsObject);
|
||||
this.scancode = jsObject.scancode;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): ReleaseKeyMacroAction {
|
||||
this.readAndAssertMacroActionId(buffer);
|
||||
this.scancode = buffer.readUInt8();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
macroActionType: macroActionType.ReleaseKeyMacroAction,
|
||||
scancode: this.scancode
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(MacroActionId.ReleaseKeyMacroAction);
|
||||
buffer.writeUInt8(this.scancode);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<ReleaseKeyMacroAction scancode="${this.scancode}">`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import {MacroAction, MacroActionId, macroActionType} from './MacroAction';
|
||||
import {KeyModifiers} from './KeyModifiers';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertUInt8} from '../assert';
|
||||
|
||||
export class ReleaseModifiersMacroAction extends MacroAction {
|
||||
|
||||
@assertUInt8
|
||||
modifierMask: number;
|
||||
|
||||
_fromJsObject(jsObject: any): ReleaseModifiersMacroAction {
|
||||
this.assertMacroActionType(jsObject);
|
||||
this.modifierMask = jsObject.modifierMask;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): ReleaseModifiersMacroAction {
|
||||
this.readAndAssertMacroActionId(buffer);
|
||||
this.modifierMask = buffer.readUInt8();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
macroActionType: macroActionType.ReleaseModifiersMacroAction,
|
||||
modifierMask: this.modifierMask
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(MacroActionId.ReleaseModifiersMacroAction);
|
||||
buffer.writeUInt8(this.modifierMask);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<ReleaseModifiersMacroAction modifierMask="${this.modifierMask}">`;
|
||||
}
|
||||
|
||||
isModifierActive(modifier: KeyModifiers): boolean {
|
||||
return (this.modifierMask & modifier) > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import {MacroAction, MacroActionId, macroActionType} from './MacroAction';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertUInt8} from '../assert';
|
||||
|
||||
export class ReleaseMouseButtonsMacroAction extends MacroAction {
|
||||
|
||||
@assertUInt8
|
||||
mouseButtonsMask: number;
|
||||
|
||||
_fromJsObject(jsObject: any): ReleaseMouseButtonsMacroAction {
|
||||
this.assertMacroActionType(jsObject);
|
||||
this.mouseButtonsMask = jsObject.mouseButtonsMask;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): ReleaseMouseButtonsMacroAction {
|
||||
this.readAndAssertMacroActionId(buffer);
|
||||
this.mouseButtonsMask = buffer.readUInt8();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
macroActionType: macroActionType.ReleaseMouseButtonsMacroAction,
|
||||
mouseButtonsMask: this.mouseButtonsMask
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(MacroActionId.ReleaseMouseButtonsMacroAction);
|
||||
buffer.writeUInt8(this.mouseButtonsMask);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<ReleaseMouseButtonsMacroAction mouseButtonsMask="${this.mouseButtonsMask}">`;
|
||||
}
|
||||
}
|
||||
44
src/config-serializer/config-items/ScrollMouseMacroAction.ts
Normal file
44
src/config-serializer/config-items/ScrollMouseMacroAction.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import {MacroAction, MacroActionId, macroActionType} from './MacroAction';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertInt16} from '../assert';
|
||||
|
||||
export class ScrollMouseMacroAction extends MacroAction {
|
||||
|
||||
@assertInt16
|
||||
x: number;
|
||||
|
||||
@assertInt16
|
||||
y: number;
|
||||
|
||||
_fromJsObject(jsObject: any): ScrollMouseMacroAction {
|
||||
this.assertMacroActionType(jsObject);
|
||||
this.x = jsObject.x;
|
||||
this.y = jsObject.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): ScrollMouseMacroAction {
|
||||
this.readAndAssertMacroActionId(buffer);
|
||||
this.x = buffer.readInt16();
|
||||
this.y = buffer.readInt16();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
macroActionType: macroActionType.ScrollMouseMacroAction,
|
||||
x: this.x,
|
||||
y: this.y
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(MacroActionId.ScrollMouseMacroAction);
|
||||
buffer.writeInt16(this.x);
|
||||
buffer.writeInt16(this.y);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<ScrollMouseMacroAction pos="(${this.x},${this.y})">`;
|
||||
}
|
||||
}
|
||||
37
src/config-serializer/config-items/SwitchKeymapAction.ts
Normal file
37
src/config-serializer/config-items/SwitchKeymapAction.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import {keyActionType, KeyActionId, KeyAction} from './KeyAction';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertUInt8} from '../assert';
|
||||
|
||||
export class SwitchKeymapAction extends KeyAction {
|
||||
|
||||
@assertUInt8
|
||||
keymapId: number;
|
||||
|
||||
_fromJsObject(jsObject: any): SwitchKeymapAction {
|
||||
this.assertKeyActionType(jsObject);
|
||||
this.keymapId = jsObject.keymapId;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): SwitchKeymapAction {
|
||||
this.readAndAssertKeyActionId(buffer);
|
||||
this.keymapId = buffer.readUInt8();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
keyActionType: keyActionType.SwitchKeymapAction,
|
||||
keymapId: this.keymapId
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(KeyActionId.SwitchKeymapAction);
|
||||
buffer.writeUInt8(this.keymapId);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<SwitchKeymapAction keymapId="${this.keymapId}">`;
|
||||
}
|
||||
}
|
||||
50
src/config-serializer/config-items/SwitchLayerAction.ts
Normal file
50
src/config-serializer/config-items/SwitchLayerAction.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import {keyActionType, KeyActionId, KeyAction} from './KeyAction';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertEnum} from '../assert';
|
||||
|
||||
export enum LayerName {
|
||||
mod,
|
||||
fn,
|
||||
mouse
|
||||
}
|
||||
|
||||
export class SwitchLayerAction extends KeyAction {
|
||||
|
||||
isLayerToggleable: boolean;
|
||||
|
||||
@assertEnum(LayerName)
|
||||
layer: LayerName;
|
||||
|
||||
_fromJsObject(jsObject: any): SwitchLayerAction {
|
||||
this.assertKeyActionType(jsObject);
|
||||
this.layer = LayerName[<string> jsObject.layer];
|
||||
this.isLayerToggleable = jsObject.toggle;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): SwitchLayerAction {
|
||||
this.readAndAssertKeyActionId(buffer);
|
||||
this.layer = buffer.readUInt8();
|
||||
this.isLayerToggleable = buffer.readBoolean();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
keyActionType: keyActionType.SwitchLayerAction,
|
||||
layer: LayerName[this.layer],
|
||||
toggle: this.isLayerToggleable
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(KeyActionId.SwitchLayerAction);
|
||||
buffer.writeUInt8(this.layer);
|
||||
buffer.writeBoolean(this.isLayerToggleable);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<SwitchLayerAction layer="${this.layer}" toggle="${this.isLayerToggleable}">`;
|
||||
}
|
||||
|
||||
}
|
||||
35
src/config-serializer/config-items/TextMacroAction.ts
Normal file
35
src/config-serializer/config-items/TextMacroAction.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import {MacroAction, MacroActionId, macroActionType} from './MacroAction';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
|
||||
export class TextMacroAction extends MacroAction {
|
||||
|
||||
text: string;
|
||||
|
||||
_fromJsObject(jsObject: any): TextMacroAction {
|
||||
this.assertMacroActionType(jsObject);
|
||||
this.text = jsObject.text;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): TextMacroAction {
|
||||
this.readAndAssertMacroActionId(buffer);
|
||||
this.text = buffer.readString();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
macroActionType: macroActionType.TextMacroAction,
|
||||
text: this.text
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer) {
|
||||
buffer.writeUInt8(MacroActionId.TextMacroAction);
|
||||
buffer.writeString(this.text);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<TextMacroAction text="${this.text}">`;
|
||||
}
|
||||
}
|
||||
103
src/config-serializer/config-items/UhkConfiguration.ts
Normal file
103
src/config-serializer/config-items/UhkConfiguration.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import {Serializable} from '../Serializable';
|
||||
import {ModuleConfigurations} from './ModuleConfigurations';
|
||||
import {Keymap} from './Keymap';
|
||||
import {Keymaps} from './Keymaps';
|
||||
import {Macro} from './Macro';
|
||||
import {Macros} from './Macros';
|
||||
import {UhkBuffer} from '../UhkBuffer';
|
||||
import {assertUInt8, assertUInt32} from '../assert';
|
||||
|
||||
export class UhkConfiguration extends Serializable<UhkConfiguration> {
|
||||
|
||||
signature: string;
|
||||
|
||||
@assertUInt8
|
||||
dataModelVersion: number;
|
||||
|
||||
@assertUInt32
|
||||
prologue: number;
|
||||
|
||||
@assertUInt8
|
||||
hardwareId: number;
|
||||
|
||||
@assertUInt8
|
||||
brandId: number;
|
||||
|
||||
moduleConfigurations: ModuleConfigurations;
|
||||
|
||||
keymaps: Keymaps;
|
||||
|
||||
macros: Macros;
|
||||
|
||||
@assertUInt32
|
||||
epilogue: number;
|
||||
|
||||
_fromJsObject(jsObject: any): UhkConfiguration {
|
||||
this.signature = jsObject.signature;
|
||||
this.dataModelVersion = jsObject.dataModelVersion;
|
||||
this.prologue = jsObject.prologue;
|
||||
this.hardwareId = jsObject.hardwareId;
|
||||
this.brandId = jsObject.brandId;
|
||||
this.moduleConfigurations = new ModuleConfigurations().fromJsObject(jsObject.moduleConfigurations);
|
||||
this.keymaps = new Keymaps().fromJsObject(jsObject.keymaps);
|
||||
this.macros = new Macros().fromJsObject(jsObject.macros);
|
||||
this.epilogue = jsObject.epilogue;
|
||||
return this;
|
||||
}
|
||||
|
||||
_fromBinary(buffer: UhkBuffer): UhkConfiguration {
|
||||
this.signature = buffer.readString();
|
||||
this.dataModelVersion = buffer.readUInt8();
|
||||
this.prologue = buffer.readUInt32();
|
||||
this.hardwareId = buffer.readUInt8();
|
||||
this.brandId = buffer.readUInt8();
|
||||
this.moduleConfigurations = new ModuleConfigurations().fromBinary(buffer);
|
||||
this.keymaps = new Keymaps().fromBinary(buffer);
|
||||
this.macros = new Macros().fromBinary(buffer);
|
||||
this.epilogue = buffer.readUInt32();
|
||||
return this;
|
||||
}
|
||||
|
||||
_toJsObject(): any {
|
||||
return {
|
||||
signature: this.signature,
|
||||
dataModelVersion: this.dataModelVersion,
|
||||
prologue: this.prologue,
|
||||
hardwareId: this.hardwareId,
|
||||
brandId: this.brandId,
|
||||
moduleConfigurations: this.moduleConfigurations.toJsObject(),
|
||||
keymaps: this.keymaps.toJsObject(),
|
||||
macros: this.macros.toJsObject(),
|
||||
epilogue: this.epilogue
|
||||
};
|
||||
}
|
||||
|
||||
_toBinary(buffer: UhkBuffer): void {
|
||||
buffer.writeString(this.signature);
|
||||
buffer.writeUInt8(this.dataModelVersion);
|
||||
buffer.writeUInt32(this.prologue);
|
||||
buffer.writeUInt8(this.hardwareId);
|
||||
buffer.writeUInt8(this.brandId);
|
||||
this.moduleConfigurations.toBinary(buffer);
|
||||
this.keymaps.toBinary(buffer);
|
||||
this.macros.toBinary(buffer);
|
||||
buffer.writeUInt32(this.epilogue);
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return `<UhkConfiguration signature="${this.signature}">`;
|
||||
}
|
||||
|
||||
getKeymap(keymapId: number): Keymap {
|
||||
let keymaps: Keymap[] = this.keymaps.elements;
|
||||
for (let i = 0; i < keymaps.length; ++i) {
|
||||
if (keymapId === keymaps[i].id) {
|
||||
return keymaps[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getMacro(macroId: number): Macro {
|
||||
return this.macros.elements.find(macro => macroId === macro.id);
|
||||
}
|
||||
}
|
||||
164
src/config-serializer/config-schema.json
Normal file
164
src/config-serializer/config-schema.json
Normal file
@@ -0,0 +1,164 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "UHK Configuration",
|
||||
"description": "UHK Configuration",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"prologue": {
|
||||
"description": "Prologue",
|
||||
"type": "integer"
|
||||
},
|
||||
"keymaps": {
|
||||
"description": "Array of keymaps",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "Id of the keymap",
|
||||
"type": "integer"
|
||||
},
|
||||
"isDefault": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"layers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"modules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"keyActions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"keyActionType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"none",
|
||||
"keystroke",
|
||||
"switchLayer",
|
||||
"switchKeymap",
|
||||
"playMacro",
|
||||
"mouse"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"keyActionType"
|
||||
],
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"keyActionType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"mouse"
|
||||
]
|
||||
},
|
||||
"mouseAction": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"leftClick",
|
||||
"middleClick",
|
||||
"rightClick",
|
||||
"moveUp",
|
||||
"moveDown",
|
||||
"moveLeft",
|
||||
"moveRight",
|
||||
"scrollUp",
|
||||
"scrollDown",
|
||||
"scrollLeft",
|
||||
"scrollRight",
|
||||
"accelerate",
|
||||
"decelerate"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"keyActionType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"keystroke"
|
||||
]
|
||||
},
|
||||
"scancode": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"keyActionType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"switchLayer"
|
||||
]
|
||||
},
|
||||
"layer": {
|
||||
"type": "string"
|
||||
},
|
||||
"toggle": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"keyActionType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"switchKeymap"
|
||||
]
|
||||
},
|
||||
"keymapId": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"keyActionType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"playMacro"
|
||||
]
|
||||
},
|
||||
"macroId": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"keyActionType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"none"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1071
src/config-serializer/uhk-config.json
Normal file
1071
src/config-serializer/uhk-config.json
Normal file
File diff suppressed because it is too large
Load Diff
33
src/index.html
Normal file
33
src/index.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Ultimate Hacking Keyboard Configurator</title>
|
||||
<link href="vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<script src="vendor/jquery/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Google Tag Manager -->
|
||||
<noscript>
|
||||
<iframe src="//www.googletagmanager.com/ns.html?id=GTM-PQLCXB" height="0" width="0" style="display:none;visibility:hidden"></iframe>
|
||||
</noscript>
|
||||
<script>
|
||||
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
||||
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||||
})(window,document,'script','dataLayer','GTM-PQLCXB');
|
||||
</script>
|
||||
<!-- End Google Tag Manager -->
|
||||
|
||||
<main-app></main-app>
|
||||
|
||||
<script src="vendor/bootstrap/js/bootstrap.min.js"></script> <!-- TODO remove in near future -->
|
||||
<script src="vendor/sortablejs/Sortable.min.js"></script>
|
||||
<script src="vendor/select2/js/select2.min.js"></script>
|
||||
<script src="app.js"></script> <!-- TODO move to typescript and components -->
|
||||
<script src="uhk.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
79
src/keymapLegacy.html
Normal file
79
src/keymapLegacy.html
Normal file
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Ultimate Hacking Keyboard Configurator</title>
|
||||
<link href="vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="css/app.css" rel="stylesheet">
|
||||
<link href="css/macro.css" rel="stylesheet">
|
||||
<link href="css/style.css" rel="stylesheet">
|
||||
<script src="vendor/jquery/jquery.min.js"></script>
|
||||
<script>
|
||||
// This js function is here to make sure it loads before any iframe content on the page.
|
||||
function resizeIframe(ifr) {
|
||||
ifr.style.height = (ifr.contentWindow.document.body.scrollHeight + 300) + 'px';
|
||||
ifr.style.width = ifr.contentWindow.document.body.scrollWidth + 'px';
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Google Tag Manager -->
|
||||
<noscript>
|
||||
<iframe src="//www.googletagmanager.com/ns.html?id=GTM-PQLCXB"
|
||||
height="0" width="0" style="display:none;visibility:hidden"></iframe>
|
||||
</noscript>
|
||||
<script>
|
||||
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
||||
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||||
})(window,document,'script','dataLayer','GTM-PQLCXB');
|
||||
</script>
|
||||
|
||||
<div class="keymap--edit keymap--qwerty main-content__inner">
|
||||
<div class="row">
|
||||
<h1 class="col-xs-12 pane-title">
|
||||
<i class="fa fa-keyboard-o"></i>
|
||||
<span class="keymap__name pane-title__name" contenteditable="true">QWERTY</span> keymap (<span class="keymap__abbrev pane-title__abbrev" contenteditable="true">QTY</span>)
|
||||
<i class="fa fa-star-o fa-star keymap__is-default"></i>
|
||||
<i class="glyphicon glyphicon-trash keymap__remove pull-right" title="Remove keymap" data-toggle="tooltip" data-placement="left"></i>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="row">
|
||||
</div>
|
||||
<div class="row uhk--wrapper">
|
||||
<div class="col-xs-12 text-center" style="margin-bottom: 2rem;">
|
||||
<span class="uhk__layer-switcher--wrapper" role="" data-title="Layers: ">
|
||||
<button type="button" data-layer="base" class="uhk__layer-switcher btn btn-primary btn-lg current">Base</button>
|
||||
<button type="button" data-layer="mod" class="uhk__layer-switcher btn btn-default btn-lg">Mod</button>
|
||||
<button type="button" data-layer="fn" class="uhk__layer-switcher btn btn-default btn-lg">Fn</button>
|
||||
<button type="button" data-layer="mouse" class="uhk__layer-switcher btn btn-default btn-lg">Mouse</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-xs-12">
|
||||
<div class="keyboard-slider">
|
||||
<div class="item uhk__layer-wrapper uhk__layer-wrapper--base current">
|
||||
<img src="./images/base-layer.svg" class="uhk uhk--base-layer" alt="">
|
||||
</div>
|
||||
<div class="item uhk__layer-wrapper uhk__layer-wrapper--mod">
|
||||
<img src="./images/base-layer--blank.svg" class="uhk uhk--mod-layer" alt="">
|
||||
</div>
|
||||
<div class="item uhk__layer-wrapper uhk__layer-wrapper--fn">
|
||||
<img src="./images/base-layer--dvorak.svg" class="uhk uhk--fn-layer" alt="">
|
||||
</div>
|
||||
<div class="item uhk__layer-wrapper uhk__layer-wrapper--mouse">
|
||||
<img src="./images/base-layer.svg" class="uhk uhk--mouse-layer" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<iframe src="popup__iframe.html" class="key-editor__popup" frameborder="0" scrolling="no" onload="resizeIframe(this)" style="display: none;"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="vendor/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="vendor/sortablejs/Sortable.min.js"></script>
|
||||
<script src="vendor/select2/js/select2.min.js"></script>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
104
src/macro.html
Normal file
104
src/macro.html
Normal file
@@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link href="node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="node_modules/select2/dist/css/select2.min.css" rel="stylesheet">
|
||||
<link href="css/macro.css" rel="stylesheet">
|
||||
<meta charset="utf-8">
|
||||
<title>Ultimate Hacking Keyboard - Agent mockups</title>
|
||||
</head>
|
||||
<body style="padding: 50px;">
|
||||
|
||||
<!-- Google Tag Manager -->
|
||||
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-PQLCXB"
|
||||
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
|
||||
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
||||
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||||
})(window,document,'script','dataLayer','GTM-PQLCXB');</script>
|
||||
<!-- End Google Tag Manager -->
|
||||
|
||||
<h1>Ultimate Hacking Keyboard — Agent mockups</h1>
|
||||
<ul class="nav nav-pills">
|
||||
<li role="presentation"><a href="popup.html">Key action editor</a></li>
|
||||
<li role="presentation" class="active"><a href="macro.html">Macro editor</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="main-wrapper" style="margin: 50px;">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div id="listWithHandle" class="list-group col-xs-10 col-xs-offset-1">
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-mouse-pointer"></i> Move pointer by 100px leftward
|
||||
<i class="glyphicon glyphicon-pencil action--edit"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash"></i>
|
||||
</div>
|
||||
<div class="list-group-item macro-settings" style="display: none;">
|
||||
<div class="helper"></div>
|
||||
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 flex-button-wrapper">
|
||||
<button class="btn btn-primary btn-sm pull-right flex-button settings-save">Save</button>
|
||||
<button class="btn btn-default btn-sm pull-right flex-button settings-cancel" style="margin-right: .5em;">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-square"></i> Press letter A
|
||||
<i class="glyphicon glyphicon-pencil action--edit"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash"></i>
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-square"></i> Press Alt+Tab
|
||||
<i class="glyphicon glyphicon-pencil action--edit"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash"></i>
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-clock-o"></i> Delay of 235ms
|
||||
<i class="glyphicon glyphicon-pencil action--edit"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash"></i>
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-mouse-pointer"></i> Press button 1
|
||||
<i class="glyphicon glyphicon-pencil action--edit"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash"></i>
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-mouse-pointer"></i> Scroll by 150px downward
|
||||
<i class="glyphicon glyphicon-pencil action--edit"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash"></i>
|
||||
</div>
|
||||
<div class="list-group-item action--item add-new__action-item no-reorder">
|
||||
<a href="#" class="add-new__action-item--link"><i class="fa fa-plus"></i> Add new action item</a>
|
||||
</div>
|
||||
<div class="list-group-item new-macro-settings">
|
||||
<div class="helper"></div>
|
||||
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 flex-button-wrapper">
|
||||
<button class="btn btn-primary btn-sm pull-right flex-button settings-save">Save</button>
|
||||
<button class="btn btn-default btn-sm pull-right flex-button settings-cancel" style="margin-right: .5em;">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="node_modules/jquery/dist/jquery.min.js"></script>
|
||||
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||
<script src="node_modules/sortablejs/Sortable.js"></script>
|
||||
<script src="macro.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
70
src/macro.js
Normal file
70
src/macro.js
Normal file
@@ -0,0 +1,70 @@
|
||||
$(function() {
|
||||
var macroSettingsHtml = $('.macro-settings');
|
||||
var toggleSpeed = 'fast';
|
||||
var notActiveOpacity = '0.75';
|
||||
|
||||
var newMacroHtml = $('.new-macro-settings');
|
||||
|
||||
// List with handle
|
||||
Sortable.create(document.getElementById('listWithHandle'), {
|
||||
handle: '.move-handle',
|
||||
filter: '.no-reorder',
|
||||
draggable: '.list-group-item',
|
||||
animation: 150
|
||||
});
|
||||
|
||||
|
||||
$('.action--edit').on('click', function(e) {
|
||||
var $this = $(this);
|
||||
var action = $this.parent('.list-group-item');
|
||||
$('.action--item.active').removeClass('callout');
|
||||
macroSettingsHtml.removeClass('callout');
|
||||
if (macroSettingsHtml.is(':visible') && !action.hasClass('active')) {
|
||||
macroSettingsHtml.slideToggle(toggleSpeed, function() {
|
||||
$('.action--item:not(.active)').css('opacity', '1');
|
||||
$('.action--item.active').removeClass('active');
|
||||
action.toggleClass('active');
|
||||
$('.action--item:not(.active)').css('opacity', notActiveOpacity);
|
||||
|
||||
$(this).detach().insertAfter(action).slideToggle(toggleSpeed, function () {
|
||||
action.addClass('callout');
|
||||
macroSettingsHtml.addClass('callout');
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
if (!macroSettingsHtml.is(':visible')) {
|
||||
action.addClass('active');
|
||||
}
|
||||
macroSettingsHtml.detach().insertAfter(action).slideToggle(toggleSpeed, function() {
|
||||
if (macroSettingsHtml.is(':visible')) {
|
||||
$('.action--item:not(.active)').css('opacity', notActiveOpacity);
|
||||
action.addClass('callout');
|
||||
macroSettingsHtml.addClass('callout');
|
||||
}
|
||||
else {
|
||||
$('.action--item:not(.active)').css('opacity', '1');
|
||||
action.removeClass('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('.flex-button', '.macro-settings').on('click', function() {
|
||||
$('.action--item.active .action--edit').click();
|
||||
});
|
||||
|
||||
$('.flex-button', '.new-macro-settings').on('click', function() {
|
||||
newMacroHtml.slideToggle(toggleSpeed, function() {
|
||||
newMacroHtml.hide().detach();
|
||||
});
|
||||
});
|
||||
|
||||
$('.add-new__action-item').on('click', function() {
|
||||
newMacroHtml.insertAfter($(this));
|
||||
newMacroHtml.slideToggle(toggleSpeed);
|
||||
});
|
||||
|
||||
// Detach and remove this item only after all event listhere has been registered on it.
|
||||
newMacroHtml.hide().detach();
|
||||
});
|
||||
97
src/macroLegacy.html
Normal file
97
src/macroLegacy.html
Normal file
@@ -0,0 +1,97 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Ultimate Hacking Keyboard Configurator</title>
|
||||
<link href="vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="css/app.css" rel="stylesheet">
|
||||
<link href="css/macro.css" rel="stylesheet">
|
||||
<link href="css/style.css" rel="stylesheet">
|
||||
<script src="vendor/jquery/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="macro--edit main-content__inner">
|
||||
<div class="row">
|
||||
<h1 class="col-xs-12 pane-title">
|
||||
<i class="fa fa-play"></i>
|
||||
<span class="macro__name pane-title__name" contenteditable="true">Macro1</span> <i class="fa"></i>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="listWithHandle" class="list-group col-xs-10 col-xs-offset-1">
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-mouse-pointer"></i> Move pointer by 100px leftward
|
||||
<i class="glyphicon glyphicon-pencil action--edit"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash"></i>
|
||||
</div>
|
||||
<div class="list-group-item macro-settings" style="display: none;">
|
||||
<div class="helper"></div>
|
||||
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
|
||||
labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
|
||||
dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
|
||||
sit amet.</p>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 flex-button-wrapper">
|
||||
<button class="btn btn-primary btn-sm pull-right flex-button settings-save">Save</button>
|
||||
<button class="btn btn-default btn-sm pull-right flex-button settings-cancel" style="margin-right: .5em;">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-square"></i> Press letter A
|
||||
<i class="glyphicon glyphicon-pencil action--edit"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash"></i>
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-square"></i> Press Alt+Tab
|
||||
<i class="glyphicon glyphicon-pencil action--edit"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash"></i>
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-clock-o"></i> Delay of 235ms
|
||||
<i class="glyphicon glyphicon-pencil action--edit"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash"></i>
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-mouse-pointer"></i> Press button 1
|
||||
<i class="glyphicon glyphicon-pencil action--edit"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash"></i>
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-mouse-pointer"></i> Scroll by 150px downward
|
||||
<i class="glyphicon glyphicon-pencil action--edit"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash"></i>
|
||||
</div>
|
||||
<div class="list-group-item action--item add-new__action-item no-reorder">
|
||||
<a href="#" class="add-new__action-item--link"><i class="fa fa-plus"></i> Add new action item</a>
|
||||
</div>
|
||||
<div class="list-group-item new-macro-settings">
|
||||
<div class="helper"></div>
|
||||
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
|
||||
labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
|
||||
dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
|
||||
sit amet.</p>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 flex-button-wrapper">
|
||||
<button class="btn btn-primary btn-sm pull-right flex-button settings-save">Save</button>
|
||||
<button class="btn btn-default btn-sm pull-right flex-button settings-cancel" style="margin-right: .5em;">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="vendor/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="vendor/sortablejs/Sortable.min.js"></script>
|
||||
<script src="vendor/select2/js/select2.min.js"></script>
|
||||
<script src="macro.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
2
src/main-app/index.ts
Normal file
2
src/main-app/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './main-app.component';
|
||||
export * from './main-app.routes';
|
||||
@@ -1,7 +1,7 @@
|
||||
import {Component, ViewEncapsulation} from '@angular/core';
|
||||
import { ROUTER_DIRECTIVES } from '@angular/router';
|
||||
|
||||
import { SideMenuComponent } from './components/side-menu';
|
||||
import { SideMenuComponent } from '../components/side-menu';
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
@@ -1,7 +1,7 @@
|
||||
import { provideRouter, RouterConfig } from '@angular/router';
|
||||
import { keymapRoutes } from './components/keymap';
|
||||
import { macroRoutes } from './components/macro';
|
||||
import { legacyRoutes } from './components/legacy-loader';
|
||||
import { keymapRoutes } from '../components/keymap';
|
||||
import { macroRoutes } from '../components/macro';
|
||||
import { legacyRoutes } from '../components/legacy-loader';
|
||||
|
||||
export const routes: RouterConfig = [
|
||||
...keymapRoutes,
|
||||
299
src/popup.html
Normal file
299
src/popup.html
Normal file
@@ -0,0 +1,299 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link href="vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="vendor/select2/css/select2.min.css" rel="stylesheet">
|
||||
<link href="style.css" rel="stylesheet">
|
||||
<meta charset="utf-8">
|
||||
<title>Ultimate Hacking Keyboard - Agent mockups</title>
|
||||
</head>
|
||||
<body style="padding:50px">
|
||||
|
||||
<!-- Google Tag Manager -->
|
||||
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-PQLCXB"
|
||||
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
|
||||
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
||||
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||||
})(window,document,'script','dataLayer','GTM-PQLCXB');</script>
|
||||
<!-- End Google Tag Manager -->
|
||||
|
||||
<h1>Ultimate Hacking Keyboard – Agent mockups</h1>
|
||||
<ul class="nav nav-pills">
|
||||
<li role="presentation" class="active"><a href="popup.html">Key action editor</a></li>
|
||||
<li role="presentation"><a href="macro.html">Macro editor</a></li>
|
||||
</ul>
|
||||
|
||||
<!--
|
||||
Basic structure of the popover to be used with the Handlebars templates.
|
||||
-->
|
||||
<div class="popover bottom" style="display: inline-block; min-width: 541px; margin: 50px; position: relative;">
|
||||
<div class="arrow"></div>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div id="key-editor-top__target"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="key-editor-content__target"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="key-editor-bottom__target"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="vendor/jquery/jquery.min.js"></script>
|
||||
<script src="vendor/handlebars/handlebars.js"></script>
|
||||
<script src="vendor/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="vendor/select2/js/select2.min.js"></script>
|
||||
<script src="script.js"></script>
|
||||
|
||||
<!--
|
||||
Handlebars templates for the common parts of the popover.
|
||||
-->
|
||||
|
||||
<!-- Popover titlebar (where the tabs resides). -->
|
||||
<script id="key-editor-top__source" type="text/x-handlebars-template">
|
||||
<div class="popover-title menu-button-group">
|
||||
Action:
|
||||
<div class="btn-group popover-menu" role="group" aria-label="...">
|
||||
{{#each buttons}}
|
||||
<button class="btn btn-sm btn-{{type}}" data-content="{{content}}" type="button"><i class="fa {{icon}}"></i> {{title}}</button>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="popover-title menu-tabs">
|
||||
<ul class="nav nav-tabs popover-menu">
|
||||
{{#each buttons}}
|
||||
<li role="presentation"><a href="#" class="menu-tabs--item" data-content="{{content}}"><i class="fa {{icon}}"></i> {{title}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Popover footer. -->
|
||||
<script id="key-editor-bottom__source" type="text/x-handlebars-template">
|
||||
<div class="popover-actions">
|
||||
<button class="btn btn-sm btn-default" type="button">Cancel</button>
|
||||
<button class="btn btn-sm btn-primary" type="button">Remap key</button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!--
|
||||
Handlebars templates for the contents of the popover tabs.
|
||||
-->
|
||||
|
||||
<!-- Keypress action. -->
|
||||
<script id="key-editor-content__source--keypress" type="text/x-handlebars-template">
|
||||
<div class="popover-content" style="margin-bottom:2px">
|
||||
<!-- Layer selection. -->
|
||||
<div style="margin-bottom: 10px;">
|
||||
<b class="setting-label">Layer action:</b>
|
||||
<div class="btn-group btn-group-sm layer-action--buttons">
|
||||
{{#each layers}}
|
||||
<button type="button" class="btn btn-default {{primary}} {{class}}">{{name}}</button>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="global-key-setup--wrapper">
|
||||
<div class="global-key-setup">
|
||||
<!-- Primary action setup: scancode+modifiers. -->
|
||||
<div class="scancode-options">
|
||||
<b class="setting-label" style="position:relative; top:-9px; margin-right:4px;">Modifiers:</b>
|
||||
<div class="btn-toolbar modifiers" style="display:inline-block">
|
||||
<div class="btn-group btn-group-sm modifiers__left">
|
||||
{{#each modifiers.left}}
|
||||
<button type="button" class="btn btn-default {{primary}}">{{name}}</button>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm modifiers__right">
|
||||
{{#each modifiers.right}}
|
||||
<button type="button" class="btn btn-default {{primary}}">{{name}}</button>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="scancode-options" style="margin-bottom:10px; margin-top:2px">
|
||||
<b class="setting-label" style="position:relative; top:2px;">Scancode:</b>
|
||||
<select class="scancode" style="width: 200px">
|
||||
{{#each scancode}}
|
||||
<optgroup label="{{groupName}}">
|
||||
{{#each groupValues}}
|
||||
<option value="{{value}}" data-explanation="{{dataExplanation}}">{{label}}</option>
|
||||
{{/each}}
|
||||
</optgroup>
|
||||
{{/each}}
|
||||
</select>
|
||||
<!-- bof optional -->
|
||||
<!-- Icon for switching the keyboard layout preview when capturing. -->
|
||||
<!-- <i class="fa fa-eye pull-right" style="margin: 0 0 0 2rem; position: relative; top: 0.65rem;" data-toggle="tooltip" data-placement="bottom" title="Show preview keyboard."></i> -->
|
||||
<!-- eof optional -->
|
||||
<button style="display: block; margin: 0 0 0 2rem;" type="button" class="btn btn-sm btn-default pull-right btn--capture-keystroke btn--capture-keystroke__start">
|
||||
<i class="fa fa-circle" style="color:#c00"></i> Capture keystroke
|
||||
</button>
|
||||
<button style="display: none; margin: 0 0 0 2rem;" type="button" class="btn btn-sm btn-info pull-right btn--capture-keystroke btn--capture-keystroke__stop">
|
||||
<i class="fa fa-square"></i> Stop capturing
|
||||
</button>
|
||||
</div>
|
||||
<!-- bof optional -->
|
||||
<!-- Keyboard layout preview to be shown in capturing mode. -->
|
||||
<!--
|
||||
<div class="preview-wrapper">
|
||||
<img src="images/base-layer.svg" />
|
||||
</div>
|
||||
-->
|
||||
<!-- eof optional -->
|
||||
|
||||
<!-- Secondary action setup: long press action. -->
|
||||
<div style="margin-top: 3rem;">
|
||||
<b class="setting-label" style="position:relative;">Long press action:</b>
|
||||
<select class="secondary-role" style="width:135px">
|
||||
{{#each secondaryRole}}
|
||||
<option value="{{name}}">{{name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
<i class="fa fa-question-circle" style="margin-left:5px" data-toggle="tooltip" data-placement="right" title="When you press and hold the key."></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Informational text to display when a layer action is selected. -->
|
||||
<div class="disabled-state--text" style="display: none; color: #31708f; padding-right: 40px;">
|
||||
<i class="fa fa-info-circle" style="font-size: 2.6rem; float: left; padding: 1rem 1.5rem 2rem;"></i>
|
||||
When a key is configured as layer switcher key, you can't assign other functions to it.
|
||||
To assign a scancode to the key, set the <em>Layer action</em> to <em>None</em>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Mouse action. -->
|
||||
<script id="key-editor-content__source--mouse" type="text/x-handlebars-template">
|
||||
<div class="popover-content" style="margin-bottom:2px">
|
||||
<div class="row" style="padding-bottom: 1rem;">
|
||||
<div class="col-xs-6 mouse-action__card" style="">
|
||||
<b class="col-xs-12 text-center" style="margin-bottom: .5rem;">Move</b>
|
||||
<div class="buttons-row row">
|
||||
<button type="button" class="btn btn-default col-xs-2 col-xs-push-5"><i class="fa fa-arrow-up"></i></button>
|
||||
</div>
|
||||
<div class="buttons-row row">
|
||||
<button type="button" class="btn btn-default col-xs-2 col-xs-push-3"><i class="fa fa-arrow-left"></i></button>
|
||||
<button type="button" class="btn btn-default col-xs-2 col-xs-push-5"><i class="fa fa-arrow-right"></i></button><br>
|
||||
</div>
|
||||
<div class="buttons-row row">
|
||||
<button type="button" class="btn btn-default col-xs-2 col-xs-push-5"><i class="fa fa-arrow-down"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 mouse-action__card">
|
||||
<b class="col-xs-12 text-center" style="margin-bottom: .5rem;">Scroll</b>
|
||||
<div class="buttons-row row">
|
||||
<button type="button" class="btn btn-default col-xs-2 col-xs-push-5"><i class="fa fa-arrow-up"></i></button>
|
||||
</div>
|
||||
<div class="buttons-row row">
|
||||
<button type="button" class="btn btn-default col-xs-2 col-xs-push-3"><i class="fa fa-arrow-left"></i></button>
|
||||
<button type="button" class="btn btn-default col-xs-2 col-xs-push-5"><i class="fa fa-arrow-right"></i></button><br>
|
||||
</div>
|
||||
<div class="buttons-row row">
|
||||
<button type="button" class="btn btn-default col-xs-2 col-xs-push-5"><i class="fa fa-arrow-down"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="margin-top: 1rem;">
|
||||
<div class="col-xs-6 mouse-action__card" style="">
|
||||
<b class="col-xs-12 text-center" style="margin-bottom: .5rem;">Click</b>
|
||||
<div class="btn-group col-xs-12" role="group">
|
||||
<button type="button" class="btn btn-default col-xs-4">Left</button>
|
||||
<button type="button" class="btn btn-default col-xs-4">Middle</button>
|
||||
<button type="button" class="btn btn-default col-xs-4">Right</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 mouse-action__card">
|
||||
<b class="col-xs-12 text-center" style="margin-bottom: .5rem;">Speed</b>
|
||||
<div class="btn-group col-xs-12" role="group">
|
||||
<button type="button" class="btn btn-default col-xs-6"><i class="fa fa-angle-double-down"></i> decelerate</button>
|
||||
<button type="button" class="btn btn-default col-xs-6">accelerate <i class="fa fa-angle-double-up"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Macro action. -->
|
||||
<script id="key-editor-content__source--macro" type="text/x-handlebars-template">
|
||||
<div class="popover-content" style="margin-bottom:2px">
|
||||
<div style="margin-bottom:0px; margin-top:2px">
|
||||
<b style="">Macro:</b>
|
||||
<select class="macro-selector" style="width:402px">
|
||||
{{#each macros}}
|
||||
<option value="{{value}}" data-abbrev="{{abbrev}}" data-abbrev-image="{{dataAbbrevImage}}" data-image="{{dataImage}}">{{name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="macro-preview" style="opacity: .35;">
|
||||
<div class="list-group" style="margin-top: 20px;">
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-square"></i> Press a key
|
||||
<i class="glyphicon glyphicon-pencil action--edit pull-right"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash pull-right" style="margin-right: 1rem;"></i>
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-clock-o"></i> Wait some time
|
||||
<i class="glyphicon glyphicon-pencil action--edit pull-right"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash pull-right" style="margin-right: 1rem;"></i>
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-mouse-pointer"></i> Move mouse
|
||||
<i class="glyphicon glyphicon-pencil action--edit pull-right"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash pull-right" style="margin-right: 1rem;"></i>
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-square"></i> Press and hold a key
|
||||
<i class="glyphicon glyphicon-pencil action--edit pull-right"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash pull-right" style="margin-right: 1rem;"></i>
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<span class="glyphicon glyphicon-option-vertical move-handle" aria-hidden="true"></span>
|
||||
<i class="fa fa-mouse-pointer"></i> Click with mouse
|
||||
<i class="glyphicon glyphicon-pencil action--edit pull-right"></i>
|
||||
<i class="glyphicon glyphicon-trash action--trash pull-right" style="margin-right: 1rem;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Switch keymap action. -->
|
||||
<script id="key-editor-content__source--switchKeymap" type="text/x-handlebars-template">
|
||||
<div class="popover-content" style="margin-bottom:2px">
|
||||
<div style="margin-bottom:0px; margin-top:2px">
|
||||
<b style="">Keymap:</b>
|
||||
<select class="layout-switcher" style="width:402px">
|
||||
{{#each layouts}}
|
||||
<option value="{{value}}" data-abbrev="{{abbrev}}" data-abbrev-image="{{dataAbbrevImage}}" data-image="{{dataImage}}">{{name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="layout-preview">
|
||||
<img src="images/base-layer--blank.svg" />
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- None action. -->
|
||||
<script id="key-editor-content__source--none" type="text/x-handlebars-template">
|
||||
<div class="key-editor--none__description col-sm-12">
|
||||
<i class="icon fa fa-ban"></i>
|
||||
<p class="col-sm-12">This key will be unassigned and will have no functionality at all.</p>
|
||||
</div>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
294
src/popup__iframe.html
Normal file
294
src/popup__iframe.html
Normal file
@@ -0,0 +1,294 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link href="vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="vendor/select2/css/select2.min.css" rel="stylesheet">
|
||||
<link href="css/style.css" rel="stylesheet">
|
||||
<meta charset="utf-8">
|
||||
<title>Ultimate Hacking Keyboard - Agent mockups</title>
|
||||
</head>
|
||||
<body style="background-color: transparent; width: 581px; text-align: center; padding: 0 20px 20px;">
|
||||
|
||||
<!--
|
||||
Basic structure of the popover to be used with the Handlebars templates.
|
||||
-->
|
||||
<div class="popover bottom" style="display: inline-block; min-width: 577px; position: relative;">
|
||||
<div class="arrow"></div>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div id="key-editor-top__target"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="key-editor-content__target"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="key-editor-bottom__target"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="vendor/jquery/jquery.min.js"></script>
|
||||
<script src="vendor/handlebars/handlebars.min.js"></script>
|
||||
<script src="vendor/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="vendor/select2/js/select2.min.js"></script>
|
||||
<script src="script.js"></script>
|
||||
|
||||
<!--
|
||||
Handlebars templates for the common parts of the popover.
|
||||
-->
|
||||
|
||||
<!-- Popover titlebar (where the tabs resides). -->
|
||||
<script id="key-editor-top__source" type="text/x-handlebars-template">
|
||||
<div class="popover-title menu-button-group">
|
||||
Action:
|
||||
<div class="btn-group popover-menu" role="group" aria-label="...">
|
||||
{{#each buttons}}
|
||||
<button class="btn btn-sm btn-{{type}}" data-content="{{content}}" type="button"><i class="fa {{icon}}"></i> {{title}}</button>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="popover-title menu-tabs">
|
||||
<ul class="nav nav-tabs popover-menu">
|
||||
{{#each buttons}}
|
||||
<li role="presentation">
|
||||
<a href="#" class="menu-tabs--item" data-content="{{content}}">
|
||||
<i class="fa {{icon}}"></i> {{title}}
|
||||
</a>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Popover footer. -->
|
||||
<script id="key-editor-bottom__source" type="text/x-handlebars-template">
|
||||
<div class="popover-actions">
|
||||
<button class="btn btn-sm btn-default" type="button">Cancel</button>
|
||||
<button class="btn btn-sm btn-primary" type="button">Remap key</button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!--
|
||||
Handlebars templates for the contents of the popover tabs.
|
||||
-->
|
||||
|
||||
<!-- Keypress action. -->
|
||||
<script id="key-editor-content__source--keypress" type="text/x-handlebars-template">
|
||||
<div class="popover-content" style="margin-bottom:2px">
|
||||
<div class="global-key-setup--wrapper">
|
||||
<div class="global-key-setup">
|
||||
<!-- Primary action setup: scancode+modifiers. -->
|
||||
<div class="scancode-options" style="margin-bottom:10px; margin-top:2px">
|
||||
<b class="setting-label" style="position:relative; top:2px;">Scancode:</b>
|
||||
<select class="scancode" style="width: 200px">
|
||||
{{#each scancode}}
|
||||
<optgroup label="{{groupName}}">
|
||||
{{#each groupValues}}
|
||||
<option value="{{scancode}}" data-searchterm="{{searchTerm}}">{{label}}</option>
|
||||
{{/each}}
|
||||
</optgroup>
|
||||
{{/each}}
|
||||
</select>
|
||||
<!-- bof optional -->
|
||||
<!-- Icon for switching the keyboard layout preview when capturing. -->
|
||||
<!-- <i class="fa fa-eye pull-right" style="margin: 0 0 0 2rem; position: relative; top: 0.65rem;" data-toggle="tooltip" data-placement="bottom" title="Show preview keyboard."></i> -->
|
||||
<!-- eof optional -->
|
||||
<button style="display: inline-block; margin: 0 0 0 .25rem;" type="button" class="btn btn-sm btn-default btn--capture-keystroke btn--capture-keystroke__start">
|
||||
<i class="fa fa-circle" style="color:#c00"></i> Capture keystroke
|
||||
</button>
|
||||
<button style="display: none; margin: 0 0 0 .25rem;" type="button" class="btn btn-sm btn-info btn--capture-keystroke btn--capture-keystroke__stop">
|
||||
<i class="fa fa-square"></i> Stop capturing
|
||||
</button>
|
||||
</div>
|
||||
<div class="scancode-options">
|
||||
<b class="setting-label" style="position:relative; top:-9px; margin-right:4px;">Modifiers:</b>
|
||||
<div class="btn-toolbar modifiers" style="display:inline-block">
|
||||
<div class="btn-group btn-group-sm modifiers__left">
|
||||
{{#each modifiers.left}}
|
||||
<button type="button" class="btn btn-default {{primary}}">{{name}}</button>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm modifiers__right">
|
||||
{{#each modifiers.right}}
|
||||
<button type="button" class="btn btn-default {{primary}}">{{name}}</button>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- bof optional -->
|
||||
<!-- Keyboard layout preview to be shown in capturing mode. -->
|
||||
<!--
|
||||
<div class="preview-wrapper">
|
||||
<img src="images/base-layer.svg" />
|
||||
</div>
|
||||
-->
|
||||
<!-- eof optional -->
|
||||
|
||||
<!-- Secondary action setup: long press action. -->
|
||||
<div style="margin-top: 3rem;">
|
||||
<b class="setting-label" style="position:relative;">Long press action:</b>
|
||||
<select class="secondary-role" style="width:135px">
|
||||
{{#each secondaryRole}}
|
||||
{{#if groupName}}
|
||||
<optgroup label="{{groupName}}">
|
||||
{{/if}}
|
||||
{{#each groupValues}}
|
||||
<option value="{{value}}">{{label}}</option>
|
||||
{{/each}}
|
||||
{{#if groupName}}
|
||||
</optgroup>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</select>
|
||||
<i class="fa fa-question-circle" style="margin-left:5px" data-toggle="tooltip" data-placement="right" title="This action happens when the key is being held along with another key."></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Informational text to display when a layer action is selected. -->
|
||||
<div class="disabled-state--text" style="display: none; color: #31708f; padding-right: 40px;">
|
||||
<i class="fa fa-info-circle" style="font-size: 2.6rem; float: left; padding: 1rem 1.5rem 2rem;"></i>
|
||||
When a key is configured as layer switcher key, you can't assign other functions to it.
|
||||
To assign a scancode to the key, set the <em>Layer action</em> to <em>None</em>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Layer modifier/togge action. -->
|
||||
<script id="key-editor-content__source--layer" type="text/x-Handlebars-template">
|
||||
<div class="popover-content" style="margin-bottom:2px">
|
||||
<div style="margin-bottom:0px; margin-top:2px">
|
||||
<select class="layer-toggle" style="width: 100px">
|
||||
<option value="activate">Activate</option>
|
||||
<option value="toggle">Toggle</option>
|
||||
</select>
|
||||
<span> the </span>
|
||||
<select class="layer-switcher" style="width: 100px">
|
||||
<option value="mod">Mod</option>
|
||||
<option value="fn">Fn</option>
|
||||
<option value="mouse">Mouse</option>
|
||||
</select>
|
||||
<span>layer by <span class="layer-help">holding</span><span class="layer-help" style="display: none;">pressing</span> this key.</span>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Mouse action. -->
|
||||
<script id="key-editor-content__source--mouse" type="text/x-handlebars-template">
|
||||
<div class="popover-content mouse row" style="margin-bottom:2px">
|
||||
<div class="col-xs-4 mouse__action--type">
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
<li role="presentation" class="active"><a href="#" data-config="move">Move</a></li>
|
||||
<li role="presentation"><a href="#" data-config="scroll">Scroll</a></li>
|
||||
<li role="presentation"><a href="#" data-config="click">Click</a></li>
|
||||
<li role="presentation"><a href="#" data-config="speed">Speed</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-8 mouse__action--config">
|
||||
<div class="mouse__config mouse__config--move text-center">
|
||||
<div class="row">
|
||||
<button type="button" class="btn btn-default btn-lg"><i class="fa fa-arrow-up"></i></button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button type="button" class="btn btn-default btn-lg"><i class="fa fa-arrow-left"></i></button>
|
||||
<button type="button" class="btn btn-default btn-lg btn-placeholder"><i class="fa fa-square"></i></button>
|
||||
<button type="button" class="btn btn-default btn-lg"><i class="fa fa-arrow-right"></i></button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button type="button" class="btn btn-default btn-lg"><i class="fa fa-arrow-down"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: none;" class="mouse__config mouse__config--scroll text-center">
|
||||
<div class="row">
|
||||
<button type="button" class="btn btn-default btn-lg"><i class="fa fa-angle-double-up"></i></button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button type="button" class="btn btn-default btn-lg"><i class="fa fa-angle-double-left"></i></button>
|
||||
<button type="button" class="btn btn-default btn-lg btn-placeholder"><i class="fa fa-square"></i></button>
|
||||
<button type="button" class="btn btn-default btn-lg"><i class="fa fa-angle-double-right"></i></button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button type="button" class="btn btn-default btn-lg"><i class="fa fa-angle-double-down"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: none;" class="mouse__config mouse__config--click">
|
||||
<div class="btn-group col-xs-12" role="group">
|
||||
<button type="button" class="btn btn-default col-xs-4">Left</button>
|
||||
<button type="button" class="btn btn-default col-xs-4">Middle</button>
|
||||
<button type="button" class="btn btn-default col-xs-4">Right</button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: none;" class="mouse__config mouse__config--speed text-center">
|
||||
<div class="help-text--mouse-speed text-left">
|
||||
<p>Press this key along with mouse movement/scrolling to accelerate/decelerate the speed of the action.</p>
|
||||
<p>You can set the multiplier in <a href="#" title="link to the setting">link to setting</a>.</p>
|
||||
</div>
|
||||
<div class="btn-group btn-group-lg" role="group">
|
||||
<button type="button" class="btn btn-default">-</button>
|
||||
<button type="button" class="btn btn-default">+</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Macro action. -->
|
||||
<script id="key-editor-content__source--macro" type="text/x-handlebars-template">
|
||||
<div class="popover-content" style="margin-bottom:2px">
|
||||
<div style="margin-bottom:0px; margin-top:2px">
|
||||
<b style="">Play macro:</b>
|
||||
<select class="macro-selector" style="width:402px">
|
||||
{{#each macros}}
|
||||
<option value="{{value}}" data-abbrev="{{abbrev}}" data-abbrev-image="{{dataAbbrevImage}}" data-image="{{dataImage}}">{{name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="macro-preview" style="opacity: .35;">
|
||||
<div class="list-group" style="margin-top: 20px;">
|
||||
<div class="list-group-item action--item">
|
||||
<i class="fa fa-square"></i> Press a key
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<i class="fa fa-clock-o"></i> Wait some time
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<i class="fa fa-mouse-pointer"></i> Move mouse
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<i class="fa fa-square"></i> Press and hold a key
|
||||
</div>
|
||||
<div class="list-group-item action--item">
|
||||
<i class="fa fa-mouse-pointer"></i> Click with mouse
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Switch keymap action. -->
|
||||
<script id="key-editor-content__source--switchKeymap" type="text/x-handlebars-template">
|
||||
<div class="popover-content" style="margin-bottom:2px">
|
||||
<div style="margin-bottom:0px; margin-top:2px">
|
||||
<b style="">Switch to keymap:</b>
|
||||
<select class="layout-switcher" style="width:390px">
|
||||
{{#each layouts}}
|
||||
<option value="{{value}}" data-abbrev="{{abbrev}}" data-abbrev-image="{{dataAbbrevImage}}" data-image="{{dataImage}}">{{name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="layout-preview">
|
||||
<img src="images/base-layer--blank.svg" />
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- None action. -->
|
||||
<script id="key-editor-content__source--none" type="text/x-handlebars-template">
|
||||
<div class="key-editor--none__description col-sm-12">
|
||||
<p class="col-sm-12">This key is unassigned and has no functionality.</p>
|
||||
</div>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
296
src/sass/app.scss
Normal file
296
src/sass/app.scss
Normal file
@@ -0,0 +1,296 @@
|
||||
.main-content {
|
||||
margin-left: 250px;
|
||||
}
|
||||
|
||||
.sidebar-menu {
|
||||
background-color: #f5f5f5;
|
||||
border-right: 1px solid #ccc;
|
||||
position: fixed;
|
||||
overflow-y: auto;
|
||||
width: 250px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
// General list styles for the sidebar-menu.
|
||||
ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
&__level-1 {
|
||||
padding: 0.5rem 1rem;
|
||||
font-size: 2rem;
|
||||
line-height: 3rem;
|
||||
|
||||
&--item {
|
||||
margin-top: 0;
|
||||
|
||||
&:nth-child(1) {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.fa-chevron-up,
|
||||
.fa-chevron-down {
|
||||
margin-right: 1rem;
|
||||
font-size: 1.5rem;
|
||||
position: relative;
|
||||
top: 0.5rem;
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.fa-chevron-up,
|
||||
.fa-chevron-down {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// General spacing of level-1 and level-2 elements.
|
||||
&__level-1,
|
||||
&__level-2 {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
&__level-2 {
|
||||
margin-left: 15px;
|
||||
|
||||
&--item {
|
||||
padding: 0 20px 0 0;
|
||||
|
||||
&.active {
|
||||
background-color: #555;
|
||||
color: #fff;
|
||||
|
||||
.fa-star {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
}
|
||||
|
||||
// General "right side" icon theming.
|
||||
.fa.pull-right {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.fa-star {
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// General hover over menu items.
|
||||
&__level-1,
|
||||
&__level-2--item {
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu--bottom {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
.sidebar {
|
||||
&__level-1 {
|
||||
background-color: transparent;
|
||||
padding: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pane-title {
|
||||
margin-bottom: 1em;
|
||||
|
||||
&__name,
|
||||
&__abbrev {
|
||||
&[contenteditable=true] {
|
||||
border: none;
|
||||
border-bottom: 2px dotted #999;
|
||||
padding: 0 0.5rem;
|
||||
margin: 0 0.25rem;
|
||||
|
||||
&.active {
|
||||
box-shadow: 0 0 0 1px #ccc, 0 0 5px 0 #ccc;
|
||||
border-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.keymap {
|
||||
&__is-default {
|
||||
&.fa-star {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
&.fa-star-o {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: #555;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
&__remove {
|
||||
font-size: 0.75em;
|
||||
top: 0.3em;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: #900;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notification {
|
||||
padding: 1rem 1.5rem;
|
||||
box-shadow: 0 0 0 1px #000;
|
||||
border-radius: 0.5rem;
|
||||
position: absolute;
|
||||
top: 2rem;
|
||||
right: 2rem;
|
||||
z-index: 10000;
|
||||
background-color: #333;
|
||||
color: #eee;
|
||||
|
||||
&__action {
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
color: #5bc0de;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
|
||||
&:focus,
|
||||
&:active,
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
color: #5bc0de;
|
||||
}
|
||||
}
|
||||
|
||||
&__dismiss {
|
||||
position: relative;
|
||||
bottom: 1px;
|
||||
color: #ccc;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.uhk {
|
||||
&__layer-switcher {
|
||||
&--wrapper {
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: attr(data-title);
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
bottom: -0.3em;
|
||||
right: 100%;
|
||||
font-size: 2.4rem;
|
||||
padding-right: 0.25em;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.keyboard-slider {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
|
||||
.uhk__layer-wrapper {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
left: 100%;
|
||||
|
||||
&.current {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.uhk {
|
||||
max-width: 100%;
|
||||
width: 98%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.key-editor__popup {
|
||||
border: none;
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
||||
// Static setting for quick portotyping.
|
||||
position: absolute;
|
||||
top: 215px;
|
||||
left: 50%;
|
||||
margin-left: -310px;
|
||||
}
|
||||
|
||||
svg.uhk {
|
||||
rect {
|
||||
&.active {
|
||||
//TODO: use a color variable instead of the declaration below.
|
||||
fill: #337ab7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* GitHub ribbon */
|
||||
.github-fork-ribbon {
|
||||
background-color: #a00;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
position: fixed;
|
||||
right: -50px;
|
||||
bottom: 40px;
|
||||
z-index: 999999;
|
||||
/* stylelint-disable indentation */
|
||||
-webkit-transform: rotate(-45deg);
|
||||
-moz-transform: rotate(-45deg);
|
||||
-ms-transform: rotate(-45deg);
|
||||
-o-transform: rotate(-45deg);
|
||||
transform: rotate(-45deg);
|
||||
-webkit-box-shadow: 0 0 10px #888;
|
||||
-moz-box-shadow: 0 0 10px #888;
|
||||
box-shadow: 0 0 10px #888;
|
||||
/* stylelint-enable indentation */
|
||||
|
||||
a {
|
||||
border: 1px solid #faa;
|
||||
color: #fff;
|
||||
display: block;
|
||||
font: bold 81.25% 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
margin: 1px 0;
|
||||
padding: 10px 50px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 0 5px #444;
|
||||
}
|
||||
}
|
||||
93
src/sass/macro.scss
Normal file
93
src/sass/macro.scss
Normal file
@@ -0,0 +1,93 @@
|
||||
.main-wrapper {
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.action--item {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.action--item.active,
|
||||
.action--item.active:hover {
|
||||
background-color: white;
|
||||
font-weight: bold;
|
||||
color: black;
|
||||
border-color: black;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.macro-settings {
|
||||
border: 1px solid black;
|
||||
border-top-color: #999;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.macro-settings .helper {
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 13px;
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: -14px;
|
||||
}
|
||||
|
||||
.action--item.active.callout,
|
||||
.macro-settings.callout {
|
||||
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.list-group-item .move-handle:hover {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.action--edit {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.action--edit:hover {
|
||||
color: #337ab7;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.action--trash {
|
||||
float: right;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.action--trash:hover {
|
||||
color: #d9534f;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.action--edit__form {
|
||||
background-color: whtie;
|
||||
margin-left: -0.5rem;
|
||||
margin-right: -15px;
|
||||
margin-top: 15px;
|
||||
padding-top: 15px;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.flex-button-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.flex-button {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.add-new__action-item:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.add-new__action-item--link,
|
||||
.add-new__action-item--link:active,
|
||||
.add-new__action-item--link:hover {
|
||||
text-decoration: none;
|
||||
color: #337ab7;
|
||||
}
|
||||
201
src/sass/style.scss
Normal file
201
src/sass/style.scss
Normal file
@@ -0,0 +1,201 @@
|
||||
.popover {
|
||||
padding: 0;
|
||||
|
||||
&.bottom {
|
||||
> .arrow {
|
||||
border-bottom-color: #000;
|
||||
|
||||
&:after {
|
||||
border-bottom-color: #f7f7f7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popover-content {
|
||||
padding: 10px 24px;
|
||||
}
|
||||
|
||||
.popover-title {
|
||||
&.menu-tabs {
|
||||
padding: 0.5rem 0.5rem 0;
|
||||
display: block;
|
||||
|
||||
.nav-tabs {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
&.menu-button-group {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.popover-actions {
|
||||
padding: 8px 14px;
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
background-color: #f7f7f7;
|
||||
border-top: 1px solid #ebebeb;
|
||||
border-radius: 0 0 5px 5px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.select2-container {
|
||||
z-index: 100000;
|
||||
}
|
||||
|
||||
.nav-tabs > li > a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.scancode--searchterm {
|
||||
color: lightgray;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.layout-abbreviation {
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
background: #333;
|
||||
padding: 4px 8px;
|
||||
font-family: monospace;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.layout-preview img {
|
||||
max-width: 100%;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.key-editor--none__description {
|
||||
p {
|
||||
padding: 2rem 0;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.select2-item {
|
||||
position: relative;
|
||||
font-size: 1.5rem;
|
||||
|
||||
&.keymap-name--wrapper {
|
||||
padding-left: 50px;
|
||||
}
|
||||
|
||||
.layout-segment-code {
|
||||
height: 2rem;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
margin-top: -1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-wrapper {
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.global-key-setup {
|
||||
&.disabled {
|
||||
opacity: 0;
|
||||
|
||||
.setting-label {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.setting-label {
|
||||
&.disabled {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.global-key-setup--wrapper {
|
||||
position: relative;
|
||||
|
||||
.disabled-state--text {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.mouse {
|
||||
&.popover-content {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__action {
|
||||
&--type {
|
||||
.nav {
|
||||
border-right: 1px solid #ccc;
|
||||
|
||||
li {
|
||||
a {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
|
||||
&.selected {
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
a {
|
||||
&.selected {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
top: 0;
|
||||
right: -4rem;
|
||||
border-color: transparent transparent transparent #337ab7;
|
||||
border-style: solid;
|
||||
border-width: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&--config {
|
||||
.btn-placeholder {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.help-text {
|
||||
&--mouse-speed {
|
||||
margin-bottom: 2rem;
|
||||
font-size: 0.9em;
|
||||
color: #666;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select2-results {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||
line-height: 26px;
|
||||
}
|
||||
974
src/script.js
Normal file
974
src/script.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ export class DataProviderService {
|
||||
constructor() { }
|
||||
|
||||
getUHKConfig(): any {
|
||||
return require('json!../../config-serializer/uhk-config.json');
|
||||
return require('json!../config-serializer/uhk-config.json');
|
||||
}
|
||||
|
||||
getKeyboardSvgAttributes(): { viewBox: string, transform: string, fill: string } {
|
||||
|
||||
@@ -105,13 +105,13 @@ export class MapperService {
|
||||
public scanCodeToSvgImagePath(scanCode: number): string {
|
||||
let fileName: string = this.scanCodeFileName[scanCode];
|
||||
if (fileName) {
|
||||
return 'build/compiled_sprite.svg#' + fileName;
|
||||
return 'assets/compiled_sprite.svg#' + fileName;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public getIcon(iconName: string): string {
|
||||
return 'build/compiled_sprite.svg#' + this.nameToFileName.get(iconName);
|
||||
return 'assets/compiled_sprite.svg#' + this.nameToFileName.get(iconName);
|
||||
}
|
||||
|
||||
private initScanCodeTextMap(): void {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {DataProviderService} from './data-provider.service';
|
||||
|
||||
import {UhkConfiguration} from '../../config-serializer/config-items/UhkConfiguration';
|
||||
import {UhkConfiguration} from '../config-serializer/config-items/UhkConfiguration';
|
||||
|
||||
@Injectable()
|
||||
export class UhkConfigurationService {
|
||||
|
||||
26
src/tsconfig.json
Normal file
26
src/tsconfig.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"sourceMap": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"removeComments": false,
|
||||
"noImplicitAny": true,
|
||||
"suppressImplicitAnyIndexErrors": true,
|
||||
"typeRoots": [
|
||||
"../node_modules/@types"
|
||||
],
|
||||
"types": [
|
||||
"node",
|
||||
"jquery",
|
||||
"es6-shim",
|
||||
"select2"
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"config-serializer"
|
||||
]
|
||||
}
|
||||
101
src/webpack.config.js
Normal file
101
src/webpack.config.js
Normal file
@@ -0,0 +1,101 @@
|
||||
// var webpack = require("webpack");
|
||||
var SvgStore = require('webpack-svgstore-plugin');
|
||||
var webpackFailPlugin = require('webpack-fail-plugin');
|
||||
var CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
var path = require('path');
|
||||
|
||||
var rootDir = path.resolve(__dirname, '../');
|
||||
|
||||
module.exports = {
|
||||
entry: ['es6-shim', 'zone.js', 'reflect-metadata', './src/boot.ts'],
|
||||
output: {
|
||||
path: rootDir + "/dist",
|
||||
filename: "uhk.js"
|
||||
},
|
||||
devtool: 'source-map',
|
||||
resolve: {
|
||||
extensions: ['', '.webpack.js', '.web.js', '.ts', '.js'],
|
||||
modulesDirectories: ['node_modules']
|
||||
},
|
||||
module: {
|
||||
preLoaders: [
|
||||
{
|
||||
test: /(.js|.ts)$/,
|
||||
loader: 'string-replace-loader',
|
||||
query: {
|
||||
search: 'moduleId: module.id,',
|
||||
replace: '',
|
||||
flags: 'g'
|
||||
}
|
||||
}
|
||||
],
|
||||
loaders: [
|
||||
{ test: /\.ts$/, loader: 'ts-loader', exclude: /node_modules/ },
|
||||
{ test: /\.html$/, loader: 'html-loader' },
|
||||
{
|
||||
test: /\.scss$/,
|
||||
exclude: /node_modules/,
|
||||
loaders: ['raw-loader', 'sass-loader']
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
// new webpack.optimize.UglifyJsPlugin({ minimize: true })
|
||||
new SvgStore(
|
||||
[
|
||||
rootDir + '/images/icons/**/*.svg'
|
||||
],
|
||||
'./',
|
||||
{
|
||||
name: 'assets/compiled_sprite.svg',
|
||||
chunk: 'app',
|
||||
svgoOptions: {
|
||||
plugins: [
|
||||
{ removeTitle: true }
|
||||
]
|
||||
}
|
||||
}
|
||||
),
|
||||
webpackFailPlugin,
|
||||
new CopyWebpackPlugin([
|
||||
{ from: './src/*.html', flatten: true },
|
||||
{ from: './src/*.js', flatten: true },
|
||||
{
|
||||
from: 'node_modules/font-awesome/css/font-awesome.min.css',
|
||||
to: 'vendor/font-awesome/css/font-awesome.min.css'
|
||||
},
|
||||
{
|
||||
from: 'node_modules/font-awesome/fonts',
|
||||
to: 'vendor/font-awesome/fonts'
|
||||
},
|
||||
{
|
||||
from: 'node_modules/bootstrap/dist',
|
||||
to: 'vendor/bootstrap'
|
||||
},
|
||||
{
|
||||
from: 'node_modules/jquery/dist/jquery.min.*',
|
||||
to: 'vendor/jquery',
|
||||
flatten: true
|
||||
},
|
||||
{
|
||||
from: 'node_modules/sortablejs/Sortable.min.js',
|
||||
to: 'vendor/sortablejs/Sortable.min.js'
|
||||
},
|
||||
{
|
||||
from: 'node_modules/select2/dist',
|
||||
to: 'vendor/select2'
|
||||
},
|
||||
{
|
||||
from: 'images',
|
||||
to: 'images'
|
||||
},
|
||||
{
|
||||
from: 'node_modules/handlebars/dist/handlebars.min.js',
|
||||
to: 'vendor/handlebars/handlebars.min.js'
|
||||
},
|
||||
], {
|
||||
ignore: ['*.config.js']
|
||||
})
|
||||
]
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user