Skip to content
This repository has been archived by the owner on Jun 22, 2022. It is now read-only.

Better windows compatibility. #86

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 2

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
Mojibar-darwin-x64
.idea/
Binary file added app/icons/color.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/icons/color@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
1 change: 1 addition & 0 deletions app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
<span class='prepend-mag' aria-hidden='true'>🔍</span>
<input class='search js-search' type='search' placeholder='Type a keyword...' aria-label='Enter a keyword'>
<div class='results js-results' role='menu'></div>
<script type="text/javascript" src="../node_modules/twemoji/2/twemoji.min.js"></script>
<script type="text/javascript" src="search.js"></script>
<script type="text/javascript" src="settings.js"></script>
80 changes: 56 additions & 24 deletions app/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,55 @@ var emojilib = require('emojilib').lib
var emojikeys = require('emojilib').ordered
var clipboard = require('electron').clipboard
var ipc = require('electron').ipcRenderer
var wordwrap = require('wordwrap')
var index = buildIndex()
var indexKeys = Object.keys(index)
var emojikeyIndexTable = buildEmojikeyIndexTable()
var searching = false
var searchInput = document.querySelector('.js-search')
var containerElement = document.querySelector('.js-results')
var directions = {
37: 'left',
38: 'up',
39: 'right',
40: 'down'
}


// Initialize container now. Further results are simply filtered via calls to search().
containerElement.innerHTML = ''
var fragment = document.createDocumentFragment()
for(let i in emojikeys) {
let name = emojikeys[i]
let unicode = (emojilib[name]['char'] || '--')
let resultElement = document.createElement('button')
resultElement.type = 'button'
resultElement.className = 'emoji'
resultElement.id = name
resultElement.setAttribute('aria-label', name)

// For consistent retrieval, if no image could be parsed/generated.
resultElement.setAttribute('data-char', unicode)

// Parse the Twitter version of this emoji.
resultElement.innerHTML = twemoji.parse(unicode, function(icon) {
return '../node_modules/twemoji/2/svg/' + icon + '.svg'
})

// Setup title for mouse over to provide hints about what keywords trigger this emoji.
let keywords = emojilib[name].keywords.filter(function(val) {
return val != unicode
});
let title = ':' + name + ':\n\n(' + keywords.join(', ') + ')'
resultElement.title = wordwrap(50)(title)

fragment.appendChild(resultElement)
}
containerElement.appendChild(fragment)

// Init search.
searchInput.dataset.isSearchInput = true
searchInput.focus()
search('')
searchInput.addEventListener('input', function () {
search(this.value.toLowerCase())
})
Expand Down Expand Up @@ -65,13 +99,19 @@ document.addEventListener('keydown', function (evt) {
}
})

function copyFocusedEmoji (emoji, copyText) {
function copyFocusedEmoji (targetElement, copyText) {
var data

// Since focused target could be an image, retarget the parent button.
button = targetElement
if (targetElement.tagName == 'IMG') {
button = targetElement.parentNode
}

// on enter: copy data and exit
if (copyText) {
data = ':' + emoji.getAttribute('aria-label') + ':'
} else {
data = emoji.innerText
data = button.getAttribute('data-char')
if (copyText || data == '--') {
data = ':' + button.getAttribute('aria-label') + ':'
}
clipboard.writeText(data)
searchInput.value = ''
Expand Down Expand Up @@ -131,24 +171,17 @@ function search (query) {
results.unshift(query)
}

renderResults(results, document.querySelector('.js-results'))
if (document.querySelector('.emoji')) document.querySelector('.emoji').scrollIntoViewIfNeeded()
renderResults(results)
if (document.querySelector('button:not(.hide)')) document.querySelector('button:not(.hide)').scrollIntoViewIfNeeded()
}, 80)
}

function renderResults (emojiNameArray, containerElement) {
containerElement.innerHTML = ''
var fragment = document.createDocumentFragment()
emojiNameArray.forEach(function (name) {
var unicode = (emojilib[name]['char'] || '--')
var resultElement = document.createElement('button')
resultElement.type = 'button'
resultElement.className = 'emoji'
resultElement.setAttribute('aria-label', name)
resultElement.textContent = unicode
fragment.appendChild(resultElement)
function renderResults (emojiNameArray) {
// Already initialized, just hide all and show only matches.
let all = document.querySelectorAll('button')
all.forEach(function(button) {
button.classList.toggle('hide', emojiNameArray.indexOf(button.id) === -1)
})
containerElement.appendChild(fragment)
}

function buildEmojikeyIndexTable () {
Expand Down Expand Up @@ -185,12 +218,11 @@ function isWord (charCode) {
}

function jumpto (destination) {
var container = document.getElementsByClassName('js-results')[0]
var all = document.getElementsByClassName('emoji')
var all = document.querySelectorAll('button.emoji:not(.hide)')
var focusedElement = document.querySelector('.emoji:focus')
var nodeIndex = Array.prototype.indexOf.call(all, focusedElement)
var resultPerRow = Math.floor(container.clientWidth / all[0].clientWidth)
var resultPerCol = Math.floor(container.clientHeight / all[0].clientHeight)
var resultPerRow = Math.floor(containerElement.clientWidth / all[0].clientWidth)
var resultPerCol = Math.floor(containerElement.clientHeight / all[0].clientHeight)
var newTarget

if (destination === 'up') {
Expand Down
43 changes: 33 additions & 10 deletions app/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,24 @@ var ipc = require('electron').ipcRenderer

var defaultPreference = {
'open-window-shortcut': 'ctrl+shift+space',
'emoji-size': '20',
'open-at-login': false
'emoji-size': '40',
'window-position': 'topRight',
'open-at-login': false,
}

var preferenceNames = {
'open-window-shortcut': 'Mojibar shortcut',
'emoji-size': 'Emoji font size',
'open-at-login': 'Start Mojibar at login'
'emoji-size': 'Emoji size',
'window-position': 'Window Position',
'open-at-login': 'Start Mojibar at login',
}

var applyPreferences = function (preference, initialization) {
window.localStorage.setItem('preference', JSON.stringify(preference))

ipc.send('update-preference', preference, initialization)
var style = document.createElement('style')
style.innerText = '.emoji { font-size: ' + preference['emoji-size'] + 'px; width: ' + (Number(preference['emoji-size']) + 20) + 'px; height: ' + (Number(preference['emoji-size']) + 20) + 'px; }'
style.innerText = '.emoji { width: ' + preference['emoji-size'] + 'px; height: ' + preference['emoji-size'] + 'px; }'
document.body.appendChild(style)
}

Expand Down Expand Up @@ -71,16 +73,37 @@ var togglePreferencePanel = function () {
panel.id = 'js-preference-panel'
var html = '<form>'
Object.keys(preferenceNames).forEach(function (key) {
var prefTitle = preferenceNames[key]
var prefVal = preference[key]
html += '<div class="pref-item"><label for="' + key + '">'
if (typeof preference[key] === 'boolean') {
if (typeof defaultPreference[key] === 'boolean') {
html += '<label>'
html += '<input type="checkbox" id="' + key + '"' + (preference[key] ? 'checked' : '') + '>'
html += preferenceNames[key]
html += '<input type="checkbox" id="' + key + '"' + (prefVal ? 'checked' : '') + '>'
html += prefTitle
html += '</label>'
} else if (key == 'window-position') {
let positionOptions = {
'topLeft': 'Top Left',
'topRight': 'Top Right',
'bottomLeft': 'Bottom Left',
'bottomRight': 'Bottom Right',
'topCenter': 'Top Center',
'bottomCenter': 'Bottom Center',
'center': 'Center'
};
html += '<label for="' + key + '">'
html += prefTitle
html += '</label>'
html += '<select id="' + key + '">'
for(let opt in positionOptions) {
let title = positionOptions[opt];
html += '<option value="' + opt + '"' + (prefVal == opt ? ' selected' : '') + '>' + title + '</option>'
}
html += '</select>'
} else {
html += preferenceNames[key]
html += prefTitle
html += '</label>'
html += '<input type="text" id="' + key + '" value="' + preference[key] + '" placeholder="' + defaultPreference[key] + '">'
html += '<input type="text" id="' + key + '" value="' + prefVal + '" placeholder="' + defaultPreference[key] + '">'
}
html += '</div>'
})
Expand Down
21 changes: 17 additions & 4 deletions app/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,27 @@ button {
.emoji {
overflow: hidden;
float: left;
padding: 10px;
padding: 0;
width: 40px;
height: 40px;
font-size: 20px;
font-family: "AppleColorEmoji", "Noto Color Emoji", "EmojiOne Color", sans-serif;
-webkit-appearance: none;
background: transparent;
border: 0;
position: relative;
}

/* Make image relative to button size, centered x/y. */
.emoji img {
width: 70%;
position: absolute;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
height: 70%;
}

.hide {
display: none;
}

.on-preference {
Expand Down Expand Up @@ -103,7 +116,7 @@ button {
margin-bottom: 8px;
}

.preference-panel input {
.preference-panel input, .preference-panel select {
padding: 10px 13px;
font-size: 13px;
border-radius: 3px;
Expand Down
22 changes: 15 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
var { app, ipcMain, globalShortcut, Menu } = require('electron')
var isWin = /^win/.test(process.platform)
var isMac = /darwin/.test(process.platform)
var iconType = (isWin ? 'color' : 'monotone'); // Will vary depending on OS. TODO: Should we be checking isMac instead (since Linux may have same issue)?
var menubar = require('menubar')
var mb = menubar({ dir: __dirname + '/app', width: 440, height: 270, icon: __dirname + '/app/Icon-Template.png', preloadWindow: true, windowPosition: 'topRight', alwaysOnTop: true })
var mb = menubar({ dir: __dirname + '/app', width: 440, height: 270, icon: __dirname + '/app/icons/' + iconType + '.png', preloadWindow: true, windowPosition: 'topRight', alwaysOnTop: true })
var isDev = require('electron-is-dev')

mb.on('show', function () {
Expand Down Expand Up @@ -31,8 +34,13 @@ ipcMain.on('update-preference', function (evt, pref, initialization) {
openAsHidden: true
})
}

mb.setOption('windowPosition', pref['window-position'])
})

// Since Windows/Linux use 'control' key and only Mac uses 'command'.
var superHotKey = isMac ? 'CommandOrControl' : 'Control+Shift'

var template = [
{
label: 'Mojibar',
Expand Down Expand Up @@ -69,22 +77,22 @@ var template = [
},
{
label: 'Reload',
accelerator: 'CmdOrCtrl+R',
accelerator: 'CommandOrControl+R',
click: function (item, focusedWindow) { if (focusedWindow) focusedWindow.reload() }
},
{
label: 'Preference',
accelerator: 'CommandOrControl+,',
accelerator: superHotKey + '+,',
click: function () { mb.window.webContents.send('open-preference') }
},
{
label: 'Quit App',
accelerator: 'CommandOrControl+Q',
selector: 'terminate:'
},
accelerator: superHotKey + '+Q',
click: function () { app.quit() }
},
{
label: 'Toggle DevTools',
accelerator: 'Alt+CommandOrControl+I',
accelerator: (isMac ? 'Alt+CommandOrControl' : 'Control+Shift') + '+I',
click: function () { mb.window.toggleDevTools() }
}
]
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
"dependencies": {
"electron-is-dev": "^0.1.2",
"emojilib": "2.0.7",
"menubar": "^5.1.0"
"menubar": "^5.1.0",
"twemoji": "^2.2.5",
"wordwrap": "^1.0.0"
},
"devDependencies": {
"electron": "^1.4.0",
Expand Down
Loading