diff --git a/.gitignore b/.gitignore index 793b673..657cd03 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ dist/ node_modules/ npm-debug.log - +ui/css/* diff --git a/api/index.js b/api/index.js new file mode 100644 index 0000000..831026a --- /dev/null +++ b/api/index.js @@ -0,0 +1,508 @@ +var fs = require('fs') +var pull = require('pull-stream') +var multicb = require('multicb') +var pl = require('pull-level') +var pushable = require('pull-pushable') +var paramap = require('pull-paramap') +var cat = require('pull-cat') +var Notify = require('pull-notify') +var toPull = require('stream-to-pull-stream') +var ref = require('ssb-ref') +var pathlib = require('path') +var u = require('./util') + +exports.name = 'patchwork' +exports.version = '1.0.0' +exports.manifest = require('./manifest') +exports.permissions = require('./permissions') + +exports.init = function (sbot, opts) { + + var api = {} + var phoenixdb = sbot.sublevel('patchwork') + var db = { + isread: phoenixdb.sublevel('isread'), + subscribed: phoenixdb.sublevel('subscribed') + } + var state = { + // indexes (lists of {key:, ts:}) + mymsgs: [], + home: u.index(), // also has `.isread` + inbox: u.index(), // also has `.isread` and `.author` + votes: u.index(), // also has `.isread`, `.vote`, and `.votemsg` + myvotes: u.index(), // also has `.vote` + follows: u.index(), // also has `.isread` and `.following` + + // views + profiles: {}, + sites: {}, + names: {}, // ids -> names + ids: {}, // names -> ids + actionItems: {} + } + + var processor = require('./processor')(sbot, db, state, emit) + pull(pl.read(sbot.sublevel('log'), { live: true, onSync: onPrehistorySync }), pull.drain(processor)) + + // track sync state + // - processor does async processing for each message that comes in + // - awaitSync() waits for that processing to finish + // - pinc() on message arrival, pdec() on message processed + // - nP === 0 => all messages processed + var nP = 0, syncCbs = [] + function awaitSync (cb) { + if (nP > 0) + syncCbs.push(cb) + else cb() + } + state.pinc = function () { nP++ } + state.pdec = function () { + nP-- + if (nP === 0) { + syncCbs.forEach(function (cb) { cb() }) + syncCbs.length = 0 + } + } + + var isPreHistorySynced = false // track so we dont emit events for old messages + // grab for history sync + state.pinc() + function onPrehistorySync () { + console.log('Log history read...') + // when all current items finish, consider prehistory synced (and start emitting) + awaitSync(function () { + console.log('Indexes generated') + isPreHistorySynced = true + }) + // release + state.pdec() + } + + // events stream + var notify = Notify() + function emit (type, data) { + if (!isPreHistorySynced) + return + var e = data || {} + e.type = type + if (e.type == 'index-change') { + api.getIndexCounts(function (err, counts) { + e.total = counts[e.index] + e.unread = counts[e.index+'Unread'] + notify(e) + }) + } else + notify(e) + } + + // getters + + api.createEventStream = function () { + return notify.listen() + } + + api.getPaths = function (cb) { + cb(null, { + site: pathlib.join(opts.path, 'publish') + }) + } + + api.getMyProfile = function (cb) { + awaitSync(function () { + api.getProfile(sbot.id, cb) + }) + } + + function isInboxFriend (row) { + if (row.author == sbot.id) return true + var p = state.profiles[sbot.id] + if (!p) return false + return p.assignedTo[row.author] && p.assignedTo[row.author].following + } + + api.getIndexCounts = function (cb) { + awaitSync(function () { + cb(null, { + inbox: state.inbox.rows.filter(isInboxFriend).length, + inboxUnread: state.inbox.filter(function (row) { return isInboxFriend(row) && row.author != sbot.id && !row.isread }).length, + votes: state.votes.filter(function (row) { return row.vote > 0 }).length, + votesUnread: state.votes.filter(function (row) { return row.vote > 0 && !row.isread }).length, + follows: state.follows.filter(function (row) { return row.following }).length, + followsUnread: state.follows.filter(function (row) { return row.following && !row.isread }).length, + home: state.home.rows.length + }) + }) + } + + api.createInboxStream = indexStreamFn(state.inbox, function (row) { + if (!isInboxFriend(row)) return false + return row.key + }) + api.createVoteStream = indexStreamFn(state.votes, function (row) { + if (row.vote <= 0) return false + return row.votemsg + }) + api.createMyvoteStream = indexStreamFn(state.myvotes, function (row) { + if (row.vote <= 0) return false + return row.key + }) + api.createFollowStream = indexStreamFn(state.follows) + api.createHomeStream = indexStreamFn(state.home) + + function indexMarkRead (indexname, key, keyname) { + if (Array.isArray(key)) { + key.forEach(function (k) { + indexMarkRead(indexname, k, keyname) + }) + return + } + + var index = state[indexname] + var row = index.find(key, keyname) + if (row) { + var wasread = row.isread + row.isread = true + if (!wasread) + emit('index-change', { index: indexname }) + } + } + + function indexMarkUnread (indexname, key, keyname) { + if (Array.isArray(key)) { + key.forEach(function (k) { + indexMarkUnread(indexname, k, keyname) + }) + return + } + + var index = state[indexname] + var row = index.find(key, keyname) + if (row) { + var wasread = row.isread + row.isread = false + if (wasread) + emit('index-change', { index: indexname }) + } + } + + api.markRead = function (key, cb) { + indexMarkRead('inbox', key) + indexMarkRead('votes', key, 'votemsg') + indexMarkRead('follows', key) + if (Array.isArray(key)) + db.isread.batch(key.map(function (k) { return { type: 'put', key: k, value: 1 }}), cb) + else + db.isread.put(key, 1, cb) + } + api.markUnread = function (key, cb) { + indexMarkUnread('inbox', key) + indexMarkUnread('votes', key, 'votemsg') + indexMarkUnread('follows', key) + if (Array.isArray(key)) + db.isread.batch(key.map(function (k) { return { type: 'del', key: k }}), cb) + else + db.isread.del(key, cb) + } + api.toggleRead = function (key, cb) { + api.isRead(key, function (err, v) { + if (!v) { + api.markRead(key, function (err) { + cb(err, true) + }) + } else { + api.markUnread(key, function (err) { + cb(err, false) + }) + } + }) + } + api.isRead = function (key, cb) { + if (Array.isArray(key)) { + var done = multicb({ pluck: 1 }) + key.forEach(function (k, i) { + var cb = done() + db.isread.get(k, function (err, v) { cb(null, !!v) }) + }) + done(cb) + } else { + db.isread.get(key, function (err, v) { + cb && cb(null, !!v) + }) + } + } + + api.subscribe = function (key, cb) { + db.subscribed.put(key, 1, cb) + } + api.unsubscribe = function (key, cb) { + db.subscribed.del(key, cb) + } + api.toggleSubscribed = function (key, cb) { + api.isSubscribed(key, function (err, v) { + if (!v) { + api.subscribe(key, function (err) { + cb(err, true) + }) + } else { + api.unsubscribe(key, function (err) { + cb(err, false) + }) + } + }) + } + api.isSubscribed = function (key, cb) { + db.subscribed.get(key, function (err, v) { + cb && cb(null, !!v) + }) + } + + api.addFileToBlobs = function (path, cb) { + pull( + toPull.source(fs.createReadStream(path)), + sbot.blobs.add(function (err, hash) { + if (err) + cb(err) + else { + var ext = pathlib.extname(path) + if (ext == '.png' || ext == '.jpg' || ext == '.jpeg') { + var res = getImgDim(path) + res.hash = hash + cb(null, res) + } else + cb(null, { hash: hash }) + } + }) + ) + } + api.saveBlobToFile = function (hash, path, cb) { + pull( + sbot.blobs.get(hash), + toPull.sink(fs.createWriteStream(path), cb) + ) + } + function getImgDim (path) { + var NativeImage = require('native-image') + var ni = NativeImage.createFromPath(path) + return ni.getSize() + } + + var lookupcodeRegex = /(@[a-z0-9\/\+\=]+\.[a-z0-9]+)(?:\[via\])?(.+)?/i + api.useLookupCode = function (code) { + var eventPush = pushable() + + // parse and validate the code + var id, addrs + var parts = lookupcodeRegex.exec(code) + var valid = true + if (parts) { + id = parts[1] + addrs = (parts[2]) ? parts[2].split(',') : [] + + // validate id + if (!ref.isFeedId(id)) + valid = false + + // parse addresses + addrs = addrs + .map(function (addr) { + addr = addr.split(':') + if (addr.length === 3) + return { host: addr[0], port: +addr[1], key: addr[2] } + }) + .filter(Boolean) + } else + valid = false + + if (!valid) { + eventPush.push({ type: 'error', message: 'Invalid lookup code' }) + eventPush.end() + return eventPush + } + + // begin the search! + search(addrs.concat(sbot.gossip.peers())) + function search (peers) { + var peer = peers.pop() + if (!peer) + return eventPush.end() + + // connect to the peer + eventPush.push({ type: 'connecting', addr: peer }) + sbot.connect(peer, function (err, rpc) { + if (err) { + eventPush.push({ type: 'error', message: 'Failed to connect', err: err }) + return search(peers) + } + // try a sync + sync(rpc, function (err, seq) { + if (seq > 0) { + // success! + eventPush.push({ type: 'finished', seq: seq }) + eventPush.end() + } else + search(peers) // try next + }) + }) + } + + function sync (rpc, cb) { + // fetch the feed + var seq + eventPush.push({ type: 'syncing', id: id }) + pull( + rpc.createHistoryStream({ id: id, keys: false }), + pull.through(function (msg) { + seq = msg.sequence + }), + sbot.createWriteStream(function (err) { + cb(err, seq) + }) + ) + } + + return eventPush + } + + api.getSite = function (id, cb) { + awaitSync(function () { cb(null, state.sites[id]) }) + } + + var sitePathRegex = /(@.*\.ed25519)(.*)/ + api.getSiteLink = function (url, cb) { + awaitSync(function () { + // parse url + var parts = sitePathRegex.exec(url) + if (!parts) { + var err = new Error('Not found') + err.notFound = true + return cb(err) + } + + var pid = parts[1] + var path = parts[2] + if (path.charAt(0) == '/') + path = path.slice(1) // skip the preceding slash + if (!path) + path = 'index.html' // default asset + + // lookup the link + var link = (state.sites[pid]) ? state.sites[pid][path] : null + if (!link) { + var err = new Error('Not found') + err.notFound = true + return cb(err) + } + cb(null, link) + }) + } + + api.getProfile = function (id, cb) { + awaitSync(function () { cb(null, state.profiles[id]) }) + } + api.getAllProfiles = function (cb) { + awaitSync(function () { cb(null, state.profiles) }) + } + api.getNamesById = function (cb) { + awaitSync(function () { cb(null, state.names) }) + } + api.getName = function (id, cb) { + awaitSync(function () { cb(null, state.names[id]) }) + } + api.getIdsByName = function (cb) { + awaitSync(function () { cb(null, state.ids) }) + } + api.getActionItems = function (cb) { + awaitSync(function () { cb(null, state.actionItems) }) + } + + // helper to get an option off an opt function (avoids the `opt || {}` pattern) + function o (opts, k, def) { + return opts && opts[k] !== void 0 ? opts[k] : def + } + + // helper to get messages from an index + function indexStreamFn (index, getkey) { + return function (opts) { + // emulate the `ssb.createFeedStream` interface + var lt = o(opts, 'lt') + var lte = o(opts, 'lte') + var gt = o(opts, 'gt') + var gte = o(opts, 'gte') + var limit = o(opts, 'limit') + + // lt, lte, gt, gte should look like: + // [msg.value.timestamp, msg.value.author] + + // helper to create emittable rows + function lookup (row) { + if (!row) return + var key = (getkey) ? getkey(row) : row.key + if (key) { + var rowcopy = { key: key } + for (var k in row) { // copy index attrs into rowcopy + if (!rowcopy[k]) rowcopy[k] = row[k] + } + return rowcopy + } + } + + // helper to fetch rows + function fetch (row, cb) { + sbot.get(row.key, function (err, value) { + // if (err) { + // suppress this error + // the message isnt in the local cache (yet) + // but it got into the index, likely due to a link + // instead of an error, we'll put a null there to indicate the gap + // } + row.value = value + cb(null, row) + }) + } + + // readstream + var readPush = pushable() + var read = pull(readPush, paramap(fetch)) + + // await sync, then emit the reads + awaitSync(function () { + var added = 0 + for (var i=0; i < index.rows.length; i++) { + var row = index.rows[i] + + if (limit && added >= limit) + break + + // we're going to only look at timestamp, because that's all that phoenix cares about + var invalid = !!( + (lt && row.ts >= lt[0]) || + (lte && row.ts > lte[0]) || + (gt && row.ts <= gt[0]) || + (gte && row.ts < gte[0]) + ) + if (invalid) + continue + + var r = lookup(row) + if (r) { + readPush.push(r) + added++ + } + } + readPush.end() + }) + + if (opts && opts.live) { + // live stream, concat the live-emitter on the end + index.on('add', onadd) + var livePush = pushable(function () { index.removeListener('add', onadd) }) + function onadd (row) { livePush.push(lookup(row)) } + var live = pull(livePush, paramap(fetch)) + return cat([read, live]) + } + return read + } + } + + return api +} \ No newline at end of file diff --git a/api/manifest.js b/api/manifest.js new file mode 100644 index 0000000..2528352 --- /dev/null +++ b/api/manifest.js @@ -0,0 +1,38 @@ +module.exports = { + createEventStream: 'source', + getPaths: 'async', + + getIndexCounts: 'async', + createInboxStream: 'source', + createVoteStream: 'source', + createMyvoteStream: 'source', + createFollowStream: 'source', + createHomeStream: 'source', + + markRead: 'async', + markUnread: 'async', + toggleRead: 'async', + isRead: 'async', + + subscribe: 'async', + unsubscribe: 'async', + toggleSubscribed: 'async', + isSubscribed: 'async', + + addFileToBlobs: 'async', + saveBlobToFile: 'async', + + useLookupCode: 'source', + + getMyProfile: 'async', + getProfile: 'async', + getAllProfiles: 'async', + + getSite: 'async', + getSiteLink: 'async', + + getNamesById: 'async', + getName: 'async', + getIdsByName: 'async', + getActionItems: 'async' +} \ No newline at end of file diff --git a/api/permissions.js b/api/permissions.js new file mode 100644 index 0000000..0323fff --- /dev/null +++ b/api/permissions.js @@ -0,0 +1 @@ +module.exports = { anonymous: { allow: [] } } // allow nothing unless master \ No newline at end of file diff --git a/api/processor.js b/api/processor.js new file mode 100644 index 0000000..6297506 --- /dev/null +++ b/api/processor.js @@ -0,0 +1,370 @@ +var mlib = require('ssb-msgs') +var u = require('./util') + +module.exports = function (sbot, db, state, emit) { + + var processors = { + post: function (msg) { + var me = getProfile(sbot.id) + var author = msg.value.author + var by_me = (author === sbot.id) + var c = msg.value.content + + // home index + if (c.recps) + return // skip targeted messages + + state.home.sortedUpsert(msg.value.timestamp, msg.key) + if (mlib.link(c.root, 'msg')) { + // a reply, put its *parent* in the home index + state.pinc() + u.getRootMsg(sbot, msg, function (err, rootmsg) { + if (rootmsg && typeof rootmsg.value.content != 'string') // dont put encrypted msgs in homestream + state.home.sortedUpsert(rootmsg.value.timestamp, rootmsg.key) + state.pdec() + }) + } + + if (!by_me) { + // emit home-add if by a followed user and in the last hour + if (follows(sbot.id, author) && ((Date.now() - msg.value.timestamp) < 1000*60*60)) + emit('home-add') + } + + // inbox index + if (!by_me) { + var inboxed = false + mlib.links(c.root, 'msg').forEach(function (link) { + if (inboxed) return + // a reply to my messages? + if (state.mymsgs.indexOf(link.link) >= 0) { + var row = state.inbox.sortedInsert(msg.value.timestamp, msg.key) + attachIsRead(row) + row.author = msg.value.author // inbox index is filtered on read by the friends graph + if (follows(sbot.id, row.author)) + emit('index-change', { index: 'inbox' }) + inboxed = true + } + }) + mlib.links(c.mentions, 'feed').forEach(function (link) { + if (inboxed) return + // mentions me? + if (link.link == sbot.id) { + var row = state.inbox.sortedInsert(msg.value.timestamp, msg.key) + attachIsRead(row) + row.author = msg.value.author // inbox index is filtered on read by the friends graph + if (follows(sbot.id, row.author)) + emit('index-change', { index: 'inbox' }) + inboxed = true + } + }) + } + }, + + site: function (msg) { + var site = getSite(msg.value.author) + + // additions + mlib.links(msg.value.content.includes, 'blob').forEach(function (link) { + if (!link.path) + return + site[link.path] = link + }) + + // removals + var excludes = msg.value.content.excludes + if (excludes) { + ;(Array.isArray(excludes) ? excludes : [excludes]).forEach(function (item) { + if (!item.path) + return + delete site[item.path] + }) + } + }, + + contact: function (msg) { + // update profiles + mlib.links(msg.value.content.contact, 'feed').forEach(function (link) { + var toself = link.link === msg.value.author + if (toself) updateSelfContact(msg.value.author, msg) + else updateOtherContact(msg.value.author, link.link, msg) + }) + }, + + about: function (msg) { + // update profiles + mlib.links(msg.value.content.about, 'feed').forEach(function (link) { + var toself = link.link === msg.value.author + if (toself) updateSelfContact(msg.value.author, msg) + else updateOtherContact(msg.value.author, link.link, msg) + }) + }, + + vote: function (msg) { + // update tallies + var link = mlib.link(msg.value.content.vote, 'msg') + + if (link) { + if (msg.value.author == sbot.id) + updateMyVote(msg, link) + else if (state.mymsgs.indexOf(link.link) >= 0) // vote on my msg? + updateVoteOnMymsg(msg, link) + } + }, + + flag: function (msg) { + // inbox index + var link = mlib.link(msg.value.content.flag, 'msg') + if (sbot.id != msg.value.author && link && state.mymsgs.indexOf(link.link) >= 0) { + var row = state.inbox.sortedInsert(msg.value.timestamp, msg.key) + attachIsRead(row) + row.author = msg.value.author // inbox index is filtered on read by the friends graph + if (follows(sbot.id, msg.value.author)) + emit('index-change', { index: 'inbox' }) + } + + // user flags + var link = mlib.link(msg.value.content.flag, 'feed') + if (link) { + var source = getProfile(msg.value.author) + var target = getProfile(link.link) + + var flag = link.reason ? { key: msg.key, reason: link.reason } : false + source.assignedTo[target.id].flagged = flag + target.assignedBy[source.id].flagged = flag + + // track if by local user + if (source.id === sbot.id) + target.flagged = flag + } + } + } + + function getProfile (pid) { + if (pid.id) // already a profile? + return pid + + var profile = state.profiles[pid] + if (!profile) { + state.profiles[pid] = profile = { + id: pid, + + // current values... + self: { name: null, image: null }, // ...set by self about self + assignedBy: {}, // ...set by others about self + assignedTo: {}, // ...set by self about others + + // has local user flagged? + flagged: false + } + } + return profile + } + + function getSite (pid) { + var site = state.sites[pid] + if (!site) + state.sites[pid] = site = {} + return site + } + + function updateSelfContact (author, msg) { + var c = msg.value.content + author = getProfile(author) + + // name: a non-empty string + if (nonEmptyStr(c.name)) { + author.self.name = makeNameSafe(c.name) + rebuildNamesFor(author) + } + + // image: link to image + if ('image' in c) { + if (mlib.link(c.image, 'blob')) + author.self.image = mlib.link(c.image) + else if (!c.image) + delete author.self.image + } + } + + function updateOtherContact (source, target, msg) { + var c = msg.value.content + source = getProfile(source) + target = getProfile(target) + source.assignedTo[target.id] = source.assignedTo[target.id] || {} + target.assignedBy[source.id] = target.assignedBy[source.id] || {} + var userProf = getProfile(sbot.id) + + // name: a non-empty string + if (nonEmptyStr(c.name)) { + source.assignedTo[target.id].name = makeNameSafe(c.name) + target.assignedBy[source.id].name = makeNameSafe(c.name) + rebuildNamesFor(target) + } + + // following: bool + if (typeof c.following === 'boolean') { + source.assignedTo[target.id].following = c.following + target.assignedBy[source.id].following = c.following + + // if from the user, update names (in case un/following changes conflict status) + if (source.id == sbot.id) + rebuildNamesFor(target) + + // follows index + if (target.id == sbot.id) { + // use the follower's id as the key to this index, so we only have 1 entry per other user max + var row = state.follows.sortedUpsert(msg.value.timestamp, msg.key) + row.following = c.following + attachIsRead(row, msg.key) + } + } + + // blocking: bool + if (typeof c.blocking === 'boolean') { + source.assignedTo[target.id].blocking = c.blocking + target.assignedBy[source.id].blocking = c.blocking + } + } + + function rebuildNamesFor (profile) { + profile = getProfile(profile) + + // remove oldname from id->name map + var oldname = state.names[profile.id] + if (oldname) { + if (state.ids[oldname] == profile.id) { + // remove + delete state.ids[oldname] + } else if (Array.isArray(state.ids[oldname])) { + // is in a conflict, remove from conflict array + var i = state.ids[oldname].indexOf(profile.id) + if (i !== -1) { + state.ids[oldname].splice(i, 1) + if (state.ids[oldname].length === 1) { + // conflict resolved + delete state.actionItems[oldname] + state.ids[oldname] = state.ids[oldname][0] + } + } + } + } + + // default to self-assigned name + var name = profile.self.name + if (profile.id !== sbot.id && profile.assignedBy[sbot.id] && profile.assignedBy[sbot.id].name) { + // use name assigned by the local user, if one is given + name = profile.assignedBy[sbot.id].name + } + if (!name) + return + + // store + state.names[profile.id] = name + + // if following, update id->name map + if (profile.id === sbot.id || profile.assignedBy[sbot.id] && profile.assignedBy[sbot.id].following) { + if (!state.ids[name]) { // no conflict? + // take it + state.ids[name] = profile.id + } else { + // keep track of all assigned ids + if (Array.isArray(state.ids[name])) + state.ids[name].push(profile.id) + else + state.ids[name] = [state.ids[name], profile.id] + // conflict, this needs to be handled by the user + state.actionItems[name] = { + type: 'name-conflict', + name: name, + ids: state.ids[name] + } + } + } + } + + function updateMyVote (msg, l) { + // myvotes index + var row = state.myvotes.sortedUpsert(msg.value.timestamp, l.link) + row.vote = l.value + } + + function updateVoteOnMymsg (msg, l) { + // votes index + // construct a composite key which will be the same for all votes by this user on the given target + var votekey = l.link + '::' + msg.value.author // lonnng fucking key + var row = state.votes.sortedUpsert(msg.value.timestamp, votekey) + row.vote = l.value + row.votemsg = msg.key + if (row.vote > 0) attachIsRead(row, msg.key) + else row.isread = true // we dont care about non-upvotes + } + + function attachIsRead (indexRow, key) { + key = key || indexRow.key + state.pinc() + db.isread.get(key, function (err, v) { + state.pdec() + indexRow.isread = !!v + }) + } + + function follows (a, b) { + var aT = getProfile(a).assignedTo[b] + return (a != b && aT && aT.following) + } + + // exported api + + function fn (logkey) { + state.pinc() + var key = logkey.value + sbot.get(logkey.value, function (err, value) { + var msg = { key: key, value: value } + try { + // encrypted? try to decrypt + if (typeof value.content == 'string' && value.content.slice(-4) == '.box') { + value.content = sbot.private.unbox(value.content) + if (!value.content) + return state.pdec() + + // put all decrypted messages in the inbox index + var row = state.inbox.sortedInsert(msg.value.timestamp, msg.key) + attachIsRead(row) + row.author = msg.value.author // inbox index is filtered on read by the friends graph + if (follows(sbot.id, msg.value.author)) + emit('index-change', { index: 'inbox' }) + } + + // collect keys of user's messages + if (msg.value.author === sbot.id) + state.mymsgs.push(msg.key) + + // type processing + var process = processors[msg.value.content.type] + if (process) + process(msg) + } + catch (e) { + // :TODO: use sbot logging plugin + console.error('Failed to process message', e, e.stack, key, value) + } + state.pdec() + }) + } + + return fn +} + +function nonEmptyStr (str) { + return (typeof str === 'string' && !!(''+str).trim()) + } + +// allow A-z0-9._-, dont allow a trailing . +var badNameCharsRegex = /[^A-z0-9\._-]/g +function makeNameSafe (str) { + str = str.replace(badNameCharsRegex, '_') + if (str.charAt(str.length - 1) == '.') + str = str.slice(0, -1) + '_' + return str +} \ No newline at end of file diff --git a/api/test/indexes.js b/api/test/indexes.js new file mode 100644 index 0000000..b469b0d --- /dev/null +++ b/api/test/indexes.js @@ -0,0 +1,389 @@ +var multicb = require('multicb') +var tape = require('tape') +var ssbkeys = require('ssb-keys') +var pull = require('pull-stream') +var u = require('./util') + +tape('inbox index includes encrypted messages from followeds', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob'] }, // Note, does not follow charlie + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + var done = multicb() + users.bob.add(ssbkeys.box({ type: 'post', text: 'hello from bob' }, [users.alice.keys, users.bob.keys]), done()) + users.charlie.add(ssbkeys.box({ type: 'post', text: 'hello from charlie' }, [users.alice.keys, users.charlie.keys]), done()) + done(function (err) { + if (err) throw err + + pull(sbot.patchwork.createInboxStream(), pull.collect(function (err, msgs) { + if (err) throw err + t.equal(msgs.length, 1) + t.equal(msgs[0].value.author, users.bob.id) + t.end() + sbot.close() + })) + }) + }) +}) + +tape('inbox index includes replies to the users posts from followeds', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob'] }, // Note, does not follow charlie + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + users.alice.add({ type: 'post', text: 'hello from alice' }, function (err, msg) { + if (err) throw err + + var done = multicb() + users.bob.add({ type: 'post', text: 'hello from bob', root: msg.key, branch: msg.key }, done()) + users.charlie.add({ type: 'post', text: 'hello from charlie', root: msg.key, branch: msg.key }, done()) + done(function (err) { + if (err) throw err + + pull(sbot.patchwork.createInboxStream(), pull.collect(function (err, msgs) { + if (err) throw err + t.equal(msgs.length, 1) + t.equal(msgs[0].value.author, users.bob.id) + t.end() + sbot.close() + })) + }) + }) + }) +}) + +tape('inbox index includes mentions of the user from followeds', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob'] }, // Note, does not follow charlie + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + var done = multicb() + users.bob.add({ type: 'post', text: 'hello from bob', mentions: [users.alice.id] }, done()) + users.charlie.add({ type: 'post', text: 'hello from charlie', mentions: [users.alice.id] }, done()) + done(function (err) { + if (err) throw err + + pull(sbot.patchwork.createInboxStream(), pull.collect(function (err, msgs) { + if (err) throw err + t.equal(msgs.length, 1) + t.equal(msgs[0].value.author, users.bob.id) + t.end() + sbot.close() + })) + }) + }) +}) + +tape('inbox index counts correctly track read/unread', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob'] }, // Note, does not follow charlie + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + var done = multicb() + users.bob.add({ type: 'post', text: 'hello from bob', mentions: [users.alice.id] }, done()) + users.charlie.add({ type: 'post', text: 'hello from charlie', mentions: [users.alice.id] }, done()) + done(function (err, msgs) { + if (err) throw err + var inboxedMsg = msgs[0][1] + + sbot.patchwork.getIndexCounts(function (err, counts) { + if (err) throw err + t.equal(counts.inbox, 1) + t.equal(counts.inboxUnread, 1) + + sbot.patchwork.markRead(inboxedMsg.key, function (err) { + if (err) throw err + + sbot.patchwork.getIndexCounts(function (err, counts) { + if (err) throw err + t.equal(counts.inbox, 1) + t.equal(counts.inboxUnread, 0) + + sbot.patchwork.markUnread(inboxedMsg.key, function (err) { + if (err) throw err + + sbot.patchwork.getIndexCounts(function (err, counts) { + if (err) throw err + t.equal(counts.inbox, 1) + t.equal(counts.inboxUnread, 1) + + t.end() + sbot.close() + }) + }) + }) + }) + }) + }) + }) +}) + +tape('vote index includes upvotes on the users posts', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob'] }, // Note, does not follow charlie + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + users.alice.add({ type: 'post', text: 'hello from alice' }, function (err, msg) { + if (err) throw err + + var done = multicb() + users.bob.add({ type: 'vote', vote: { link: msg.key, value: 1 } }, done()) + users.charlie.add({ type: 'vote', vote: { link: msg.key, value: 1 } }, done()) + done(function (err) { + if (err) throw err + + pull(sbot.patchwork.createVoteStream(), pull.collect(function (err, msgs) { + if (err) throw err + t.equal(msgs.length, 2) + t.end() + sbot.close() + })) + }) + }) + }) +}) + +tape('vote index does not include downvotes, and removes unvotes', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob'] }, // Note, does not follow charlie + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + users.alice.add({ type: 'post', text: 'hello from alice' }, function (err, msg) { + if (err) throw err + + var done = multicb() + users.bob.add({ type: 'vote', vote: { link: msg.key, value: -1 } }, done()) + users.charlie.add({ type: 'vote', vote: { link: msg.key, value: 1 } }, done()) + users.charlie.add({ type: 'vote', vote: { link: msg.key, value: 0 } }, done()) + done(function (err) { + if (err) throw err + + pull(sbot.patchwork.createVoteStream(), pull.collect(function (err, msgs) { + if (err) throw err + t.equal(msgs.length, 0) + t.end() + sbot.close() + })) + }) + }) + }) +}) + +tape('vote index counts correctly track read/unread', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob'] }, // Note, does not follow charlie + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + users.alice.add({ type: 'post', text: 'hello from alice' }, function (err, msg) { + if (err) throw err + + var done = multicb() + users.bob.add({ type: 'vote', vote: { link: msg.key, value: 1 } }, done()) + users.charlie.add({ type: 'vote', vote: { link: msg.key, value: 1 } }, done()) + done(function (err, msgs) { + if (err) throw err + var voteMsg = msgs[0][1] + + sbot.patchwork.getIndexCounts(function (err, counts) { + if (err) throw err + t.equal(counts.votes, 2) + t.equal(counts.votesUnread, 2) + + sbot.patchwork.markRead(voteMsg.key, function (err) { + if (err) throw err + + sbot.patchwork.getIndexCounts(function (err, counts) { + if (err) throw err + t.equal(counts.votes, 2) + t.equal(counts.votesUnread, 1) + + sbot.patchwork.markUnread(voteMsg.key, function (err) { + if (err) throw err + + sbot.patchwork.getIndexCounts(function (err, counts) { + if (err) throw err + t.equal(counts.votes, 2) + t.equal(counts.votesUnread, 2) + t.end() + sbot.close() + }) + }) + }) + }) + }) + }) + }) + }) +}) + +tape('follow index includes all new followers', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: {}, + bob: { follows: ['alice'] }, + charlie: { follows: ['alice'] } + }, function (err, users) { + if (err) throw err + + pull(sbot.patchwork.createFollowStream(), pull.collect(function (err, msgs) { + if (err) throw err + t.equal(msgs.length, 2) + t.end() + sbot.close() + })) + }) +}) + +tape('follow index includes unfollows', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: {}, + bob: { follows: ['alice'] }, + charlie: { follows: ['alice'] } + }, function (err, users) { + if (err) throw err + + users.charlie.add({ type: 'contact', contact: users.alice.id, following: false }, function (err) { + if (err) throw err + pull(sbot.patchwork.createFollowStream(), pull.collect(function (err, msgs) { + if (err) throw err + t.equal(msgs.length, 3) + t.end() + sbot.close() + })) + }) + }) +}) + +tape('follow index counts correctly track read/unread', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: {}, + bob: { follows: ['alice'] }, + charlie: { follows: ['alice'] } + }, function (err, users, msgs) { + if (err) throw err + var followMsg = msgs[1][1] + + console.log('getting indexes 1') + sbot.patchwork.getIndexCounts(function (err, counts) { + if (err) throw err + t.equal(counts.follows, 2) + t.equal(counts.followsUnread, 2) + + console.log('marking read') + sbot.patchwork.markRead(followMsg.key, function (err) { + if (err) throw err + + console.log('getting indexes 2') + sbot.patchwork.getIndexCounts(function (err, counts) { + if (err) throw err + t.equal(counts.follows, 2) + t.equal(counts.followsUnread, 1) + + sbot.patchwork.markUnread(followMsg.key, function (err) { + if (err) throw err + + sbot.patchwork.getIndexCounts(function (err, counts) { + if (err) throw err + t.equal(counts.follows, 2) + t.equal(counts.followsUnread, 2) + + t.end() + sbot.close() + }) + }) + }) + }) + }) + }) +}) + +tape('home index includes all posts', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob'] }, // Note, does not follow charlie + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + users.alice.add({ type: 'post', text: 'hello from alice' }, function (err, msg) { + if (err) throw err + + var done = multicb() + users.bob.add({ type: 'post', text: 'hello from bob' }, done()) + users.charlie.add({ type: 'post', text: 'hello from charlie', root: msg.key, branch: msg.key }, done()) + done(function (err) { + if (err) throw err + + pull(sbot.patchwork.createHomeStream(), pull.collect(function (err, msgs) { + if (err) throw err + t.equal(msgs.length, 3) + t.end() + sbot.close() + })) + }) + }) + }) +}) + +tape('home index includes non-posts with post replies on them', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob'] }, // Note, does not follow charlie + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + users.alice.add({ type: 'nonpost', text: 'hello from alice' }, function (err, msg) { + if (err) throw err + + var done = multicb() + users.bob.add({ type: 'nonpost', text: 'hello from bob' }, done()) + users.charlie.add({ type: 'post', text: 'hello from charlie', root: msg.key, branch: msg.key }, done()) + done(function (err) { + if (err) throw err + + pull(sbot.patchwork.createHomeStream(), pull.collect(function (err, msgs) { + if (err) throw err + t.equal(msgs.length, 2) + t.equal(msgs[0].value.author, users.charlie.id) + t.equal(msgs[1].value.author, users.alice.id) + t.end() + sbot.close() + })) + }) + }) + }) +}) + diff --git a/api/test/names.js b/api/test/names.js new file mode 100644 index 0000000..f2763e7 --- /dev/null +++ b/api/test/names.js @@ -0,0 +1,220 @@ +var multicb = require('multicb') +var tape = require('tape') +var u = require('./util') + +tape('names default to self-assigned', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob', 'charlie'] }, + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + sbot.patchwork.getNamesById(function (err, names) { + if (err) throw err + t.equal(names[users.alice.id], 'alice') + t.equal(names[users.bob.id], 'bob') + t.equal(names[users.charlie.id], 'charlie') + + sbot.patchwork.getIdsByName(function (err, ids) { + if (err) throw err + t.equal(ids.alice, users.alice.id) + t.equal(ids.bob, users.bob.id) + t.equal(ids.charlie, users.charlie.id) + t.end() + sbot.close() + }) + }) + }) +}) + +tape('the local users name assignments take precedence', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob', 'charlie'] }, + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + var done = multicb() + users.alice.add({ type: 'about', about: users.bob.id, name: 'robert' }, done()) + users.alice.add({ type: 'about', about: users.charlie.id, name: 'chuck' }, done()) + done(function (err) { + if (err) throw err + + sbot.patchwork.getNamesById(function (err, names) { + if (err) throw err + t.equal(names[users.alice.id], 'alice') + t.equal(names[users.bob.id], 'robert') + t.equal(names[users.charlie.id], 'chuck') + + sbot.patchwork.getIdsByName(function (err, ids) { + if (err) throw err + t.equal(ids.alice, users.alice.id) + t.equal(ids.robert, users.bob.id) + t.equal(ids.chuck, users.charlie.id) + t.end() + sbot.close() + }) + }) + }) + }) +}) + +tape('conflicting names between followeds are tracked as action items', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob', 'charlie'] }, + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + users.charlie.add({ type: 'about', about: users.charlie.id, name: 'bob' }, function (err) { + if (err) throw err + + sbot.patchwork.getNamesById(function (err, names) { + if (err) throw err + t.equal(names[users.alice.id], 'alice') + t.equal(names[users.bob.id], 'bob') + t.equal(names[users.charlie.id], 'bob') + + sbot.patchwork.getIdsByName(function (err, ids) { + if (err) throw err + t.equal(ids.alice, users.alice.id) + t.equal(ids.bob.length, 2) + + sbot.patchwork.getActionItems(function (err, items) { + if (err) throw err + t.equal(items.bob.type, 'name-conflict') + t.equal(items.bob.name, 'bob') + t.equal(items.bob.ids.length, 2) + t.end() + sbot.close() + }) + }) + }) + }) + }) +}) + +tape('conflicting names are resolved by unfollowing', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob', 'charlie'] }, + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + users.charlie.add({ type: 'about', about: users.charlie.id, name: 'bob' }, function (err) { + if (err) throw err + + users.alice.add({ type: 'contact', contact: users.bob.id, following: false }, function (err) { + if (err) throw err + + sbot.patchwork.getNamesById(function (err, names) { + if (err) throw err + t.equal(names[users.alice.id], 'alice') + t.equal(names[users.bob.id], 'bob') + t.equal(names[users.charlie.id], 'bob') + + sbot.patchwork.getIdsByName(function (err, ids) { + if (err) throw err + t.equal(ids.alice, users.alice.id) + t.equal(ids.bob, users.charlie.id) + + sbot.patchwork.getActionItems(function (err, items) { + if (err) throw err + t.equal(Object.keys(items).length, 0) + t.end() + sbot.close() + }) + }) + }) + }) + }) + }) +}) + +tape('conflicting names are resolved by one of the users self-assigning a new name', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob', 'charlie'] }, + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + users.charlie.add({ type: 'about', about: users.charlie.id, name: 'bob' }, function (err) { + if (err) throw err + + users.bob.add({ type: 'about', about: users.bob.id, name: 'robert' }, function (err) { + if (err) throw err + + sbot.patchwork.getNamesById(function (err, names) { + if (err) throw err + t.equal(names[users.alice.id], 'alice') + t.equal(names[users.bob.id], 'robert') + t.equal(names[users.charlie.id], 'bob') + + sbot.patchwork.getIdsByName(function (err, ids) { + if (err) throw err + t.equal(ids.alice, users.alice.id) + t.equal(ids.robert, users.bob.id) + t.equal(ids.bob, users.charlie.id) + + sbot.patchwork.getActionItems(function (err, items) { + if (err) throw err + t.equal(Object.keys(items).length, 0) + t.end() + sbot.close() + }) + }) + }) + }) + }) + }) +}) + +tape('conflicting names are resolved by the local user assigning a new name', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob', 'charlie'] }, + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + users.charlie.add({ type: 'about', about: users.charlie.id, name: 'bob' }, function (err) { + if (err) throw err + + users.alice.add({ type: 'about', about: users.bob.id, name: 'robert' }, function (err) { + if (err) throw err + + sbot.patchwork.getNamesById(function (err, names) { + if (err) throw err + t.equal(names[users.alice.id], 'alice') + t.equal(names[users.bob.id], 'robert') + t.equal(names[users.charlie.id], 'bob') + + sbot.patchwork.getIdsByName(function (err, ids) { + if (err) throw err + t.equal(ids.alice, users.alice.id) + t.equal(ids.robert, users.bob.id) + t.equal(ids.bob, users.charlie.id) + + sbot.patchwork.getActionItems(function (err, items) { + if (err) throw err + t.equal(Object.keys(items).length, 0) + t.end() + sbot.close() + }) + }) + }) + }) + }) + }) +}) diff --git a/api/test/profiles.js b/api/test/profiles.js new file mode 100644 index 0000000..4a20a0a --- /dev/null +++ b/api/test/profiles.js @@ -0,0 +1,91 @@ +var multicb = require('multicb') +var tape = require('tape') +var u = require('./util') + +var blobid = '&RYnp9p24dlAPYGhrsFYdGGHIAYM2uM5pr1//RocCF/U=.sha256' + +tape('profiles track self-assigned name and profile pic', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob', 'charlie'] }, + bob: {}, + charlie: {} + }, function (err, users) { + if (err) throw err + + var done = multicb() + users.alice.add({ type: 'about', about: users.alice.id, image: blobid }, done()) + users.bob.add({ type: 'about', about: users.bob.id, image: blobid }, done()) + users.charlie.add({ type: 'about', about: users.charlie.id, image: blobid }, done()) + done(function (err) { + if (err) throw err + + sbot.patchwork.getAllProfiles(function (err, profiles) { + if (err) throw err + t.equal(profiles[users.alice.id].self.name, 'alice') + t.equal(profiles[users.bob.id].self.name, 'bob') + t.equal(profiles[users.charlie.id].self.name, 'charlie') + t.equal(profiles[users.alice.id].self.image.link, blobid) + t.equal(profiles[users.bob.id].self.image.link, blobid) + t.equal(profiles[users.charlie.id].self.image.link, blobid) + sbot.close() + t.end() + }) + }) + }) +}) + +tape('profiles track follows, names, and flags between users', function (t) { + var sbot = u.newserver() + u.makeusers(sbot, { + alice: { follows: ['bob', 'charlie'] }, + bob: { follows: ['alice', 'charlie'] }, + charlie: { follows: ['bob', 'alice'] } + }, function (err, users) { + if (err) throw err + + var done = multicb() + users.alice.add({ type: 'about', about: users.bob.id, name: 'robert' }, done()) + users.alice.add({ type: 'flag', flag: { link: users.charlie.id, reason: 'such a jerk!' } }, done()) + users.bob.add({ type: 'flag', flag: { link: users.charlie.id, reason: 'dont like him' } }, done()) + done(function (err) { + if (err) throw err + + sbot.patchwork.getAllProfiles(function (err, profiles) { + if (err) throw err + function by(a, b) { + return profiles[users[a].id].assignedBy[users[b].id] + } + function to(a, b) { + return profiles[users[a].id].assignedTo[users[b].id] + } + + t.equal(to('alice', 'bob').following, true) + t.equal(to('alice', 'charlie').following, true) + t.equal(by('bob', 'alice').following, true) + t.equal(by('charlie', 'alice').following, true) + + t.equal(to('bob', 'alice').following, true) + t.equal(to('bob', 'charlie').following, true) + t.equal(by('alice', 'bob').following, true) + t.equal(by('charlie', 'bob').following, true) + + t.equal(to('charlie', 'bob').following, true) + t.equal(to('charlie', 'alice').following, true) + t.equal(by('bob', 'charlie').following, true) + t.equal(by('alice', 'charlie').following, true) + + t.equal(to('alice', 'charlie').flagged.reason, 'such a jerk!') + t.equal(by('charlie', 'alice').flagged.reason, 'such a jerk!') + t.equal(to('bob', 'charlie').flagged.reason, 'dont like him') + t.equal(by('charlie', 'bob').flagged.reason, 'dont like him') + + t.equal(to('alice', 'bob').name, 'robert') + t.equal(by('bob', 'alice').name, 'robert') + + sbot.close() + t.end() + }) + }) + }) +}) diff --git a/api/test/util.js b/api/test/util.js new file mode 100644 index 0000000..3b234e0 --- /dev/null +++ b/api/test/util.js @@ -0,0 +1,52 @@ +var path = require('path') +var fs = require('fs') +var rimraf = require('rimraf') +var osenv = require('osenv') +var multicb = require('multicb') +var ssbkeys = require('ssb-keys') + +var createSbot = require('scuttlebot') + .use(require('scuttlebot/plugins/master')) + .use(require('scuttlebot/plugins/gossip')) + .use(require('scuttlebot/plugins/friends')) + .use(require('scuttlebot/plugins/replicate')) + .use(require('scuttlebot/plugins/blobs')) + .use(require('scuttlebot/plugins/invite')) + .use(require('scuttlebot/plugins/block')) + .use(require('scuttlebot/plugins/logging')) + .use(require('scuttlebot/plugins/private')) + .use(require('../')) + +var n = 0 +exports.newserver = function () { + var dir = path.join(osenv.tmpdir(), 'phoenix-api-test'+(++n)) + rimraf.sync(dir) + fs.mkdirSync(dir) + + return createSbot({ path: dir, keys: ssbkeys.generate() }) +} + +exports.makeusers = function (sbot, desc, cb) { + var users = { alice: sbot.createFeed(sbot.keys) } + var done = multicb() + + // generate feeds + for (var name in desc) { + if (!users[name]) + users[name] = sbot.createFeed(ssbkeys.generate()) + console.log(name+':', users[name].id) + } + + // generate additional messages + for (var name in desc) { + ;(desc[name].follows||[]).forEach(function (name2) { + users[name].add({ type: 'contact', contact: users[name2].id, following: true }, done()) + }) + users[name].add({ type: 'contact', contact: users[name].id, name: name }, done()) + } + + done(function (err, msgs) { + if (err) cb(err) + else cb(null, users, msgs) + }) +} \ No newline at end of file diff --git a/api/util.js b/api/util.js new file mode 100644 index 0000000..40b006a --- /dev/null +++ b/api/util.js @@ -0,0 +1,92 @@ +var mlib = require('ssb-msgs') +var EventEmitter = require('events').EventEmitter + +module.exports.index = function () { + var index = new EventEmitter() + index.rows = [] + + index.sortedInsert = function (ts, key) { + var row = { ts: ts, key: key } + for (var i=0; i < index.rows.length; i++) { + if (index.rows[i].ts < ts) { + index.rows.splice(i, 0, row) + index.emit('add', row) + return row + } + } + index.rows.push(row) + index.emit('add', row) + return row + } + + index.sortedUpsert = function (ts, key) { + var i = index.indexOf(key) + if (i !== -1) { + // readd to index at new TS + if (index.rows[i].ts < ts) { + var oldrow = index.rows[i] + index.rows.splice(i, 1) + var newrow = index.sortedInsert(ts, key) + for (var k in oldrow) { + if (k != 'ts') + newrow[k] = oldrow[k] + } + return newrow + } else + return index.rows[i] + } else { + // add to index + return index.sortedInsert(ts, key) + } + } + + index.indexOf = function (key, keyname) { + keyname = keyname || 'key' + for (var i=0; i < index.rows.length; i++) { + if (index.rows[i][keyname] === key) + return i + } + return -1 + } + + index.find = function (key, keyname) { + var i = index.indexOf(key, keyname) + if (i !== -1) + return index.rows[i] + return null + } + + index.contains = function (key) { + return index.indexOf(index, key) !== -1 + } + + index.filter = index.rows.filter.bind(index.rows) + + return index +} + + +module.exports.getRootMsg = function (sbot, msg, cb) { + var mid = mlib.link(msg.value.content.root || msg.value.content.branch, 'msg').link + up() + function up () { + sbot.get(mid, function (err, msgvalue) { + if (err) + return cb(err) + + // not found? stop here + if (!msgvalue) + return cb() + + // ascend + var link = mlib.link(msgvalue.content.root || msgvalue.content.branch, 'msg') + if (link) { + mid = link.link + return up() + } + + // topmost, finish + cb(null, { key: mid, value: msgvalue }) + }) + } +} \ No newline at end of file diff --git a/app/index.js b/app/index.js index 919df86..e2afd9f 100644 --- a/app/index.js +++ b/app/index.js @@ -17,7 +17,7 @@ var createSbot = require('scuttlebot') .use(require('scuttlebot/plugins/block')) .use(require('scuttlebot/plugins/logging')) .use(require('scuttlebot/plugins/private')) - .use(require('ssb-patchwork-api')) + .use(require('../api')) config.keys = ssbKeys.loadOrCreateSync(path.join(config.path, 'secret')) if(config.keys.curve === 'k256') @@ -42,7 +42,7 @@ app.on('ready', function () { // open main window var mainWindow = windows.open( - 'file://' + path.join(__dirname, '../node_modules/ssb-patchwork-ui/main.html'), + 'file://' + path.join(__dirname, '../ui/main.html'), sbot, blobs, { width: 1030, height: 720 } diff --git a/package.json b/package.json index 41cd72d..e160596 100644 --- a/package.json +++ b/package.json @@ -5,10 +5,12 @@ "main": "app/index.js", "scripts": { "start": "electron .", + "test": "set -e; for t in api/test/*.js; do node $t; done", "clean": "rm -Rf ./dist", "clean:osx": "rm -Rf ./dist/osx", "clean:win": "rm -Rf ./dist/win", - "build": "npm run clean && npm run build:osx && npm run build:win", + "build": "npm run clean && npm run build:ui && npm run build:osx && npm run build:win", + "build:ui": "mkdir -p ./ui/css; lessc ./ui/less/main.less ./ui/css/main.css", "build:icon": "./scripts/make-icns.sh assets/icon1024.png assets/osx/scuttlebot.icns", "build:osx": "electron-packager ./ Scuttlebot --out=dist/osx --platform=darwin --arch=x64 --ignore=node_modules/electron* --version=0.28.3 --icon=assets/osx/scuttlebot.icns", "build:win": "electron-packager ./ Scuttlebot --out=dist/win --platform=win32 --arch=ia32 --ignore=node_modules/electron* --version=0.28.3 --icon=assets/win/scuttlebot.ico", @@ -22,7 +24,11 @@ "devDependencies": { "electron-builder": "^2.0.0", "electron-packager": "^4.1.3", - "electron-prebuilt": "^0.28.2" + "electron-prebuilt": "^0.28.2", + "less": "~1.7.5", + "osenv": "~0.1.0", + "rimraf": "~2.2.8", + "tape": "~3.0.0" }, "dependencies": { "multiblob": "^1.5.0", @@ -34,8 +40,26 @@ "scuttlebot": "~7.0.2", "ssb-config": "^1.0.3", "ssb-keys": "^4.0.3", - "ssb-patchwork-api": "~0.0.7", - "ssb-patchwork-ui": "~0.0.18", - "stream-to-pull-stream": "^1.6.1" + "stream-to-pull-stream": "^1.6.1", + "blob-to-buffer": "^1.2.3", + "emoji-named-characters": "^1.0.1", + "hyperscript": "~1.4.6", + "mime-types": "^2.1.3", + "nicedate": "~0.0.0", + "observable": "^2.1.3", + "once": "~1.3.1", + "phoenix-router": "~1.0.0", + "published-working-tree": "~0.0.0", + "pull-cat": "^1.1.7", + "pull-merge": "~1.0.2", + "pull-paramap": "^1.1.3", + "pull-stream-to-stream": "~1.3.0", + "ssb-marked": "~0.5.0", + "ssb-msg-schemas": "~5.0.0", + "ssb-msgs": "~5.0.0", + "ssb-ref": "~2.2.0", + "suggest-box": "~1.1.6", + "pull-level": "~1.2.0", + "pull-notify": "0.0.0" } } diff --git a/ui/blob-search.html b/ui/blob-search.html new file mode 100644 index 0000000..0499612 --- /dev/null +++ b/ui/blob-search.html @@ -0,0 +1,27 @@ + + + + Searching... - Secure Scuttlebutt + + + + + +
+
+
+

Scanning the network for this file...

+
+

File ... has not been downloaded yet.

+
+

Your computer is querying other computers for the file. This may take some time.

+
+
+
+
+
+
+
+ + + diff --git a/ui/blob-search.js b/ui/blob-search.js new file mode 100644 index 0000000..9cd9069 --- /dev/null +++ b/ui/blob-search.js @@ -0,0 +1,23 @@ +'use strict' +var ipc = require('ipc') +var SSBClient = require('./lib/muxrpc-ipc') + +var ssb = SSBClient() +var params = ipc.sendSync('fetch-params') +document.getElementById('fileid').innerHTML = params.hash + +// periodically poll for the file +var poll = setInterval(pollBlob, 10e3) + +function pollBlob () { + console.log('checking...') //18e0c49bdf14018dd2ad7caafb4291630339615a0e306243c8cfffafb53233a2 + ssb.blobs.has(params.hash, function (err, has) { + if (has || true) { + console.log('blob found') + clearInterval(poll) + document.title = 'File Located - Secure Scuttlebutt' + document.getElementById('content').innerHTML = '

Your file has been found!

Click here to open it.

' + } else + console.log('not yet found') + }) +} \ No newline at end of file diff --git a/ui/fonts/glyphicons-halflings-regular.eot b/ui/fonts/glyphicons-halflings-regular.eot new file mode 100755 index 0000000..b93a495 Binary files /dev/null and b/ui/fonts/glyphicons-halflings-regular.eot differ diff --git a/ui/fonts/glyphicons-halflings-regular.svg b/ui/fonts/glyphicons-halflings-regular.svg new file mode 100755 index 0000000..94fb549 --- /dev/null +++ b/ui/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ui/fonts/glyphicons-halflings-regular.ttf b/ui/fonts/glyphicons-halflings-regular.ttf new file mode 100755 index 0000000..1413fc6 Binary files /dev/null and b/ui/fonts/glyphicons-halflings-regular.ttf differ diff --git a/ui/fonts/glyphicons-halflings-regular.woff b/ui/fonts/glyphicons-halflings-regular.woff new file mode 100755 index 0000000..9e61285 Binary files /dev/null and b/ui/fonts/glyphicons-halflings-regular.woff differ diff --git a/ui/fonts/glyphicons-halflings-regular.woff2 b/ui/fonts/glyphicons-halflings-regular.woff2 new file mode 100755 index 0000000..64539b5 Binary files /dev/null and b/ui/fonts/glyphicons-halflings-regular.woff2 differ diff --git a/ui/img/default-prof-pic.png b/ui/img/default-prof-pic.png new file mode 100644 index 0000000..db833e4 Binary files /dev/null and b/ui/img/default-prof-pic.png differ diff --git a/ui/img/default-prof-pic.pxm b/ui/img/default-prof-pic.pxm new file mode 100644 index 0000000..23014d9 Binary files /dev/null and b/ui/img/default-prof-pic.pxm differ diff --git a/ui/img/emoji/+1.png b/ui/img/emoji/+1.png new file mode 100644 index 0000000..81786c1 Binary files /dev/null and b/ui/img/emoji/+1.png differ diff --git a/ui/img/emoji/-1.png b/ui/img/emoji/-1.png new file mode 100644 index 0000000..41c6b82 Binary files /dev/null and b/ui/img/emoji/-1.png differ diff --git a/ui/img/emoji/100.png b/ui/img/emoji/100.png new file mode 100644 index 0000000..ca3bb9b Binary files /dev/null and b/ui/img/emoji/100.png differ diff --git a/ui/img/emoji/1234.png b/ui/img/emoji/1234.png new file mode 100644 index 0000000..c47c2e1 Binary files /dev/null and b/ui/img/emoji/1234.png differ diff --git a/ui/img/emoji/8ball.png b/ui/img/emoji/8ball.png new file mode 100644 index 0000000..c2c710d Binary files /dev/null and b/ui/img/emoji/8ball.png differ diff --git a/ui/img/emoji/a.png b/ui/img/emoji/a.png new file mode 100644 index 0000000..09ff6d6 Binary files /dev/null and b/ui/img/emoji/a.png differ diff --git a/ui/img/emoji/ab.png b/ui/img/emoji/ab.png new file mode 100644 index 0000000..2a52220 Binary files /dev/null and b/ui/img/emoji/ab.png differ diff --git a/ui/img/emoji/abc.png b/ui/img/emoji/abc.png new file mode 100644 index 0000000..505d40a Binary files /dev/null and b/ui/img/emoji/abc.png differ diff --git a/ui/img/emoji/abcd.png b/ui/img/emoji/abcd.png new file mode 100644 index 0000000..5218470 Binary files /dev/null and b/ui/img/emoji/abcd.png differ diff --git a/ui/img/emoji/accept.png b/ui/img/emoji/accept.png new file mode 100644 index 0000000..2d20090 Binary files /dev/null and b/ui/img/emoji/accept.png differ diff --git a/ui/img/emoji/aerial_tramway.png b/ui/img/emoji/aerial_tramway.png new file mode 100644 index 0000000..38f6dfe Binary files /dev/null and b/ui/img/emoji/aerial_tramway.png differ diff --git a/ui/img/emoji/airplane.png b/ui/img/emoji/airplane.png new file mode 100644 index 0000000..8407cb6 Binary files /dev/null and b/ui/img/emoji/airplane.png differ diff --git a/ui/img/emoji/alarm_clock.png b/ui/img/emoji/alarm_clock.png new file mode 100644 index 0000000..86ca8c8 Binary files /dev/null and b/ui/img/emoji/alarm_clock.png differ diff --git a/ui/img/emoji/alien.png b/ui/img/emoji/alien.png new file mode 100644 index 0000000..416de47 Binary files /dev/null and b/ui/img/emoji/alien.png differ diff --git a/ui/img/emoji/ambulance.png b/ui/img/emoji/ambulance.png new file mode 100644 index 0000000..b740f45 Binary files /dev/null and b/ui/img/emoji/ambulance.png differ diff --git a/ui/img/emoji/anchor.png b/ui/img/emoji/anchor.png new file mode 100644 index 0000000..0c5192e Binary files /dev/null and b/ui/img/emoji/anchor.png differ diff --git a/ui/img/emoji/angel.png b/ui/img/emoji/angel.png new file mode 100644 index 0000000..da52c31 Binary files /dev/null and b/ui/img/emoji/angel.png differ diff --git a/ui/img/emoji/anger.png b/ui/img/emoji/anger.png new file mode 100644 index 0000000..6fb4dca Binary files /dev/null and b/ui/img/emoji/anger.png differ diff --git a/ui/img/emoji/angry.png b/ui/img/emoji/angry.png new file mode 100644 index 0000000..f95bfa8 Binary files /dev/null and b/ui/img/emoji/angry.png differ diff --git a/ui/img/emoji/anguished.png b/ui/img/emoji/anguished.png new file mode 100644 index 0000000..c625947 Binary files /dev/null and b/ui/img/emoji/anguished.png differ diff --git a/ui/img/emoji/ant.png b/ui/img/emoji/ant.png new file mode 100644 index 0000000..b92d1cc Binary files /dev/null and b/ui/img/emoji/ant.png differ diff --git a/ui/img/emoji/apple.png b/ui/img/emoji/apple.png new file mode 100644 index 0000000..08aa17b Binary files /dev/null and b/ui/img/emoji/apple.png differ diff --git a/ui/img/emoji/aquarius.png b/ui/img/emoji/aquarius.png new file mode 100644 index 0000000..cbff66e Binary files /dev/null and b/ui/img/emoji/aquarius.png differ diff --git a/ui/img/emoji/aries.png b/ui/img/emoji/aries.png new file mode 100644 index 0000000..aab5e88 Binary files /dev/null and b/ui/img/emoji/aries.png differ diff --git a/ui/img/emoji/arrow_backward.png b/ui/img/emoji/arrow_backward.png new file mode 100644 index 0000000..0886218 Binary files /dev/null and b/ui/img/emoji/arrow_backward.png differ diff --git a/ui/img/emoji/arrow_double_down.png b/ui/img/emoji/arrow_double_down.png new file mode 100644 index 0000000..2ecbebc Binary files /dev/null and b/ui/img/emoji/arrow_double_down.png differ diff --git a/ui/img/emoji/arrow_double_up.png b/ui/img/emoji/arrow_double_up.png new file mode 100644 index 0000000..2bd6659 Binary files /dev/null and b/ui/img/emoji/arrow_double_up.png differ diff --git a/ui/img/emoji/arrow_down.png b/ui/img/emoji/arrow_down.png new file mode 100644 index 0000000..e6702f0 Binary files /dev/null and b/ui/img/emoji/arrow_down.png differ diff --git a/ui/img/emoji/arrow_down_small.png b/ui/img/emoji/arrow_down_small.png new file mode 100644 index 0000000..22d383a Binary files /dev/null and b/ui/img/emoji/arrow_down_small.png differ diff --git a/ui/img/emoji/arrow_forward.png b/ui/img/emoji/arrow_forward.png new file mode 100644 index 0000000..fbfe711 Binary files /dev/null and b/ui/img/emoji/arrow_forward.png differ diff --git a/ui/img/emoji/arrow_heading_down.png b/ui/img/emoji/arrow_heading_down.png new file mode 100644 index 0000000..56dd3b9 Binary files /dev/null and b/ui/img/emoji/arrow_heading_down.png differ diff --git a/ui/img/emoji/arrow_heading_up.png b/ui/img/emoji/arrow_heading_up.png new file mode 100644 index 0000000..c8f670a Binary files /dev/null and b/ui/img/emoji/arrow_heading_up.png differ diff --git a/ui/img/emoji/arrow_left.png b/ui/img/emoji/arrow_left.png new file mode 100644 index 0000000..d64ac61 Binary files /dev/null and b/ui/img/emoji/arrow_left.png differ diff --git a/ui/img/emoji/arrow_lower_left.png b/ui/img/emoji/arrow_lower_left.png new file mode 100644 index 0000000..55fb03c Binary files /dev/null and b/ui/img/emoji/arrow_lower_left.png differ diff --git a/ui/img/emoji/arrow_lower_right.png b/ui/img/emoji/arrow_lower_right.png new file mode 100644 index 0000000..da8fb82 Binary files /dev/null and b/ui/img/emoji/arrow_lower_right.png differ diff --git a/ui/img/emoji/arrow_right.png b/ui/img/emoji/arrow_right.png new file mode 100644 index 0000000..6d483b5 Binary files /dev/null and b/ui/img/emoji/arrow_right.png differ diff --git a/ui/img/emoji/arrow_right_hook.png b/ui/img/emoji/arrow_right_hook.png new file mode 100644 index 0000000..8b4ea6e Binary files /dev/null and b/ui/img/emoji/arrow_right_hook.png differ diff --git a/ui/img/emoji/arrow_up.png b/ui/img/emoji/arrow_up.png new file mode 100644 index 0000000..b5b0688 Binary files /dev/null and b/ui/img/emoji/arrow_up.png differ diff --git a/ui/img/emoji/arrow_up_down.png b/ui/img/emoji/arrow_up_down.png new file mode 100644 index 0000000..be423de Binary files /dev/null and b/ui/img/emoji/arrow_up_down.png differ diff --git a/ui/img/emoji/arrow_up_small.png b/ui/img/emoji/arrow_up_small.png new file mode 100644 index 0000000..3f40bfb Binary files /dev/null and b/ui/img/emoji/arrow_up_small.png differ diff --git a/ui/img/emoji/arrow_upper_left.png b/ui/img/emoji/arrow_upper_left.png new file mode 100644 index 0000000..2950ae2 Binary files /dev/null and b/ui/img/emoji/arrow_upper_left.png differ diff --git a/ui/img/emoji/arrow_upper_right.png b/ui/img/emoji/arrow_upper_right.png new file mode 100644 index 0000000..e23790b Binary files /dev/null and b/ui/img/emoji/arrow_upper_right.png differ diff --git a/ui/img/emoji/arrows_clockwise.png b/ui/img/emoji/arrows_clockwise.png new file mode 100644 index 0000000..5f84d7e Binary files /dev/null and b/ui/img/emoji/arrows_clockwise.png differ diff --git a/ui/img/emoji/arrows_counterclockwise.png b/ui/img/emoji/arrows_counterclockwise.png new file mode 100644 index 0000000..3e06f5b Binary files /dev/null and b/ui/img/emoji/arrows_counterclockwise.png differ diff --git a/ui/img/emoji/art.png b/ui/img/emoji/art.png new file mode 100644 index 0000000..d45212b Binary files /dev/null and b/ui/img/emoji/art.png differ diff --git a/ui/img/emoji/articulated_lorry.png b/ui/img/emoji/articulated_lorry.png new file mode 100644 index 0000000..81ec1f9 Binary files /dev/null and b/ui/img/emoji/articulated_lorry.png differ diff --git a/ui/img/emoji/astonished.png b/ui/img/emoji/astonished.png new file mode 100644 index 0000000..858a834 Binary files /dev/null and b/ui/img/emoji/astonished.png differ diff --git a/ui/img/emoji/atm.png b/ui/img/emoji/atm.png new file mode 100644 index 0000000..c2846e7 Binary files /dev/null and b/ui/img/emoji/atm.png differ diff --git a/ui/img/emoji/b.png b/ui/img/emoji/b.png new file mode 100644 index 0000000..8742b3d Binary files /dev/null and b/ui/img/emoji/b.png differ diff --git a/ui/img/emoji/baby.png b/ui/img/emoji/baby.png new file mode 100644 index 0000000..3b29da4 Binary files /dev/null and b/ui/img/emoji/baby.png differ diff --git a/ui/img/emoji/baby_bottle.png b/ui/img/emoji/baby_bottle.png new file mode 100644 index 0000000..1b2cfe5 Binary files /dev/null and b/ui/img/emoji/baby_bottle.png differ diff --git a/ui/img/emoji/baby_chick.png b/ui/img/emoji/baby_chick.png new file mode 100644 index 0000000..9be8d29 Binary files /dev/null and b/ui/img/emoji/baby_chick.png differ diff --git a/ui/img/emoji/baby_symbol.png b/ui/img/emoji/baby_symbol.png new file mode 100644 index 0000000..2e58725 Binary files /dev/null and b/ui/img/emoji/baby_symbol.png differ diff --git a/ui/img/emoji/baggage_claim.png b/ui/img/emoji/baggage_claim.png new file mode 100644 index 0000000..59ae044 Binary files /dev/null and b/ui/img/emoji/baggage_claim.png differ diff --git a/ui/img/emoji/balloon.png b/ui/img/emoji/balloon.png new file mode 100644 index 0000000..0344897 Binary files /dev/null and b/ui/img/emoji/balloon.png differ diff --git a/ui/img/emoji/ballot_box_with_check.png b/ui/img/emoji/ballot_box_with_check.png new file mode 100644 index 0000000..f07a466 Binary files /dev/null and b/ui/img/emoji/ballot_box_with_check.png differ diff --git a/ui/img/emoji/bamboo.png b/ui/img/emoji/bamboo.png new file mode 100644 index 0000000..fc858d0 Binary files /dev/null and b/ui/img/emoji/bamboo.png differ diff --git a/ui/img/emoji/banana.png b/ui/img/emoji/banana.png new file mode 100644 index 0000000..a0563af Binary files /dev/null and b/ui/img/emoji/banana.png differ diff --git a/ui/img/emoji/bangbang.png b/ui/img/emoji/bangbang.png new file mode 100644 index 0000000..7270f0a Binary files /dev/null and b/ui/img/emoji/bangbang.png differ diff --git a/ui/img/emoji/bank.png b/ui/img/emoji/bank.png new file mode 100644 index 0000000..1faa877 Binary files /dev/null and b/ui/img/emoji/bank.png differ diff --git a/ui/img/emoji/bar_chart.png b/ui/img/emoji/bar_chart.png new file mode 100644 index 0000000..09d7301 Binary files /dev/null and b/ui/img/emoji/bar_chart.png differ diff --git a/ui/img/emoji/barber.png b/ui/img/emoji/barber.png new file mode 100644 index 0000000..a10cb23 Binary files /dev/null and b/ui/img/emoji/barber.png differ diff --git a/ui/img/emoji/baseball.png b/ui/img/emoji/baseball.png new file mode 100644 index 0000000..da004e2 Binary files /dev/null and b/ui/img/emoji/baseball.png differ diff --git a/ui/img/emoji/basketball.png b/ui/img/emoji/basketball.png new file mode 100644 index 0000000..ef694be Binary files /dev/null and b/ui/img/emoji/basketball.png differ diff --git a/ui/img/emoji/bath.png b/ui/img/emoji/bath.png new file mode 100644 index 0000000..8f75d1d Binary files /dev/null and b/ui/img/emoji/bath.png differ diff --git a/ui/img/emoji/bathtub.png b/ui/img/emoji/bathtub.png new file mode 100644 index 0000000..1c3f844 Binary files /dev/null and b/ui/img/emoji/bathtub.png differ diff --git a/ui/img/emoji/battery.png b/ui/img/emoji/battery.png new file mode 100644 index 0000000..aa7eedc Binary files /dev/null and b/ui/img/emoji/battery.png differ diff --git a/ui/img/emoji/bear.png b/ui/img/emoji/bear.png new file mode 100644 index 0000000..f5afe92 Binary files /dev/null and b/ui/img/emoji/bear.png differ diff --git a/ui/img/emoji/bee.png b/ui/img/emoji/bee.png new file mode 100644 index 0000000..f537339 Binary files /dev/null and b/ui/img/emoji/bee.png differ diff --git a/ui/img/emoji/beer.png b/ui/img/emoji/beer.png new file mode 100644 index 0000000..cd78bed Binary files /dev/null and b/ui/img/emoji/beer.png differ diff --git a/ui/img/emoji/beers.png b/ui/img/emoji/beers.png new file mode 100644 index 0000000..cc5e4ab Binary files /dev/null and b/ui/img/emoji/beers.png differ diff --git a/ui/img/emoji/beetle.png b/ui/img/emoji/beetle.png new file mode 100644 index 0000000..222577c Binary files /dev/null and b/ui/img/emoji/beetle.png differ diff --git a/ui/img/emoji/beginner.png b/ui/img/emoji/beginner.png new file mode 100644 index 0000000..1f022d1 Binary files /dev/null and b/ui/img/emoji/beginner.png differ diff --git a/ui/img/emoji/bell.png b/ui/img/emoji/bell.png new file mode 100644 index 0000000..69acceb Binary files /dev/null and b/ui/img/emoji/bell.png differ diff --git a/ui/img/emoji/bento.png b/ui/img/emoji/bento.png new file mode 100644 index 0000000..d680112 Binary files /dev/null and b/ui/img/emoji/bento.png differ diff --git a/ui/img/emoji/bicyclist.png b/ui/img/emoji/bicyclist.png new file mode 100644 index 0000000..cbbd7c3 Binary files /dev/null and b/ui/img/emoji/bicyclist.png differ diff --git a/ui/img/emoji/bike.png b/ui/img/emoji/bike.png new file mode 100644 index 0000000..6573860 Binary files /dev/null and b/ui/img/emoji/bike.png differ diff --git a/ui/img/emoji/bikini.png b/ui/img/emoji/bikini.png new file mode 100644 index 0000000..4ff63b4 Binary files /dev/null and b/ui/img/emoji/bikini.png differ diff --git a/ui/img/emoji/bird.png b/ui/img/emoji/bird.png new file mode 100644 index 0000000..e6be8c0 Binary files /dev/null and b/ui/img/emoji/bird.png differ diff --git a/ui/img/emoji/birthday.png b/ui/img/emoji/birthday.png new file mode 100644 index 0000000..36e8edc Binary files /dev/null and b/ui/img/emoji/birthday.png differ diff --git a/ui/img/emoji/black_circle.png b/ui/img/emoji/black_circle.png new file mode 100644 index 0000000..e46f9df Binary files /dev/null and b/ui/img/emoji/black_circle.png differ diff --git a/ui/img/emoji/black_joker.png b/ui/img/emoji/black_joker.png new file mode 100644 index 0000000..4c78f36 Binary files /dev/null and b/ui/img/emoji/black_joker.png differ diff --git a/ui/img/emoji/black_nib.png b/ui/img/emoji/black_nib.png new file mode 100644 index 0000000..29f6994 Binary files /dev/null and b/ui/img/emoji/black_nib.png differ diff --git a/ui/img/emoji/black_square.png b/ui/img/emoji/black_square.png new file mode 100644 index 0000000..71da10d Binary files /dev/null and b/ui/img/emoji/black_square.png differ diff --git a/ui/img/emoji/black_square_button.png b/ui/img/emoji/black_square_button.png new file mode 100644 index 0000000..f2597e9 Binary files /dev/null and b/ui/img/emoji/black_square_button.png differ diff --git a/ui/img/emoji/blossom.png b/ui/img/emoji/blossom.png new file mode 100644 index 0000000..55a9735 Binary files /dev/null and b/ui/img/emoji/blossom.png differ diff --git a/ui/img/emoji/blowfish.png b/ui/img/emoji/blowfish.png new file mode 100644 index 0000000..d3ad465 Binary files /dev/null and b/ui/img/emoji/blowfish.png differ diff --git a/ui/img/emoji/blue_book.png b/ui/img/emoji/blue_book.png new file mode 100644 index 0000000..e2b9e8c Binary files /dev/null and b/ui/img/emoji/blue_book.png differ diff --git a/ui/img/emoji/blue_car.png b/ui/img/emoji/blue_car.png new file mode 100644 index 0000000..978291e Binary files /dev/null and b/ui/img/emoji/blue_car.png differ diff --git a/ui/img/emoji/blue_heart.png b/ui/img/emoji/blue_heart.png new file mode 100644 index 0000000..baa29b3 Binary files /dev/null and b/ui/img/emoji/blue_heart.png differ diff --git a/ui/img/emoji/blush.png b/ui/img/emoji/blush.png new file mode 100644 index 0000000..3a95eb6 Binary files /dev/null and b/ui/img/emoji/blush.png differ diff --git a/ui/img/emoji/boar.png b/ui/img/emoji/boar.png new file mode 100644 index 0000000..8196ad4 Binary files /dev/null and b/ui/img/emoji/boar.png differ diff --git a/ui/img/emoji/boat.png b/ui/img/emoji/boat.png new file mode 100644 index 0000000..ff656dc Binary files /dev/null and b/ui/img/emoji/boat.png differ diff --git a/ui/img/emoji/bomb.png b/ui/img/emoji/bomb.png new file mode 100644 index 0000000..3289787 Binary files /dev/null and b/ui/img/emoji/bomb.png differ diff --git a/ui/img/emoji/book.png b/ui/img/emoji/book.png new file mode 100644 index 0000000..8b69841 Binary files /dev/null and b/ui/img/emoji/book.png differ diff --git a/ui/img/emoji/bookmark.png b/ui/img/emoji/bookmark.png new file mode 100644 index 0000000..6fc4ed9 Binary files /dev/null and b/ui/img/emoji/bookmark.png differ diff --git a/ui/img/emoji/bookmark_tabs.png b/ui/img/emoji/bookmark_tabs.png new file mode 100644 index 0000000..83782ff Binary files /dev/null and b/ui/img/emoji/bookmark_tabs.png differ diff --git a/ui/img/emoji/books.png b/ui/img/emoji/books.png new file mode 100644 index 0000000..dca06a1 Binary files /dev/null and b/ui/img/emoji/books.png differ diff --git a/ui/img/emoji/boom.png b/ui/img/emoji/boom.png new file mode 100644 index 0000000..9d5bd04 Binary files /dev/null and b/ui/img/emoji/boom.png differ diff --git a/ui/img/emoji/boot.png b/ui/img/emoji/boot.png new file mode 100644 index 0000000..58d0fdb Binary files /dev/null and b/ui/img/emoji/boot.png differ diff --git a/ui/img/emoji/bouquet.png b/ui/img/emoji/bouquet.png new file mode 100644 index 0000000..ce63783 Binary files /dev/null and b/ui/img/emoji/bouquet.png differ diff --git a/ui/img/emoji/bow.png b/ui/img/emoji/bow.png new file mode 100644 index 0000000..024cb61 Binary files /dev/null and b/ui/img/emoji/bow.png differ diff --git a/ui/img/emoji/bowling.png b/ui/img/emoji/bowling.png new file mode 100644 index 0000000..13d8ece Binary files /dev/null and b/ui/img/emoji/bowling.png differ diff --git a/ui/img/emoji/bowtie.png b/ui/img/emoji/bowtie.png new file mode 100644 index 0000000..28ff0c7 Binary files /dev/null and b/ui/img/emoji/bowtie.png differ diff --git a/ui/img/emoji/boy.png b/ui/img/emoji/boy.png new file mode 100644 index 0000000..f79f1f2 Binary files /dev/null and b/ui/img/emoji/boy.png differ diff --git a/ui/img/emoji/bread.png b/ui/img/emoji/bread.png new file mode 100644 index 0000000..7e7c637 Binary files /dev/null and b/ui/img/emoji/bread.png differ diff --git a/ui/img/emoji/bride_with_veil.png b/ui/img/emoji/bride_with_veil.png new file mode 100644 index 0000000..dd0b0cf Binary files /dev/null and b/ui/img/emoji/bride_with_veil.png differ diff --git a/ui/img/emoji/bridge_at_night.png b/ui/img/emoji/bridge_at_night.png new file mode 100644 index 0000000..495b06c Binary files /dev/null and b/ui/img/emoji/bridge_at_night.png differ diff --git a/ui/img/emoji/briefcase.png b/ui/img/emoji/briefcase.png new file mode 100644 index 0000000..46e82b0 Binary files /dev/null and b/ui/img/emoji/briefcase.png differ diff --git a/ui/img/emoji/broken_heart.png b/ui/img/emoji/broken_heart.png new file mode 100644 index 0000000..a1bc850 Binary files /dev/null and b/ui/img/emoji/broken_heart.png differ diff --git a/ui/img/emoji/bug.png b/ui/img/emoji/bug.png new file mode 100644 index 0000000..c2eaf7a Binary files /dev/null and b/ui/img/emoji/bug.png differ diff --git a/ui/img/emoji/bulb.png b/ui/img/emoji/bulb.png new file mode 100644 index 0000000..23afca1 Binary files /dev/null and b/ui/img/emoji/bulb.png differ diff --git a/ui/img/emoji/bullettrain_front.png b/ui/img/emoji/bullettrain_front.png new file mode 100644 index 0000000..16651ac Binary files /dev/null and b/ui/img/emoji/bullettrain_front.png differ diff --git a/ui/img/emoji/bullettrain_side.png b/ui/img/emoji/bullettrain_side.png new file mode 100644 index 0000000..8eca368 Binary files /dev/null and b/ui/img/emoji/bullettrain_side.png differ diff --git a/ui/img/emoji/bus.png b/ui/img/emoji/bus.png new file mode 100644 index 0000000..823aa39 Binary files /dev/null and b/ui/img/emoji/bus.png differ diff --git a/ui/img/emoji/busstop.png b/ui/img/emoji/busstop.png new file mode 100644 index 0000000..9489484 Binary files /dev/null and b/ui/img/emoji/busstop.png differ diff --git a/ui/img/emoji/bust_in_silhouette.png b/ui/img/emoji/bust_in_silhouette.png new file mode 100644 index 0000000..dd7defe Binary files /dev/null and b/ui/img/emoji/bust_in_silhouette.png differ diff --git a/ui/img/emoji/busts_in_silhouette.png b/ui/img/emoji/busts_in_silhouette.png new file mode 100644 index 0000000..1f3aabc Binary files /dev/null and b/ui/img/emoji/busts_in_silhouette.png differ diff --git a/ui/img/emoji/cactus.png b/ui/img/emoji/cactus.png new file mode 100644 index 0000000..5a2c3cc Binary files /dev/null and b/ui/img/emoji/cactus.png differ diff --git a/ui/img/emoji/cake.png b/ui/img/emoji/cake.png new file mode 100644 index 0000000..efeb9b4 Binary files /dev/null and b/ui/img/emoji/cake.png differ diff --git a/ui/img/emoji/calendar.png b/ui/img/emoji/calendar.png new file mode 100644 index 0000000..900b868 Binary files /dev/null and b/ui/img/emoji/calendar.png differ diff --git a/ui/img/emoji/calling.png b/ui/img/emoji/calling.png new file mode 100644 index 0000000..837897f Binary files /dev/null and b/ui/img/emoji/calling.png differ diff --git a/ui/img/emoji/camel.png b/ui/img/emoji/camel.png new file mode 100644 index 0000000..496c186 Binary files /dev/null and b/ui/img/emoji/camel.png differ diff --git a/ui/img/emoji/camera.png b/ui/img/emoji/camera.png new file mode 100644 index 0000000..397d03b Binary files /dev/null and b/ui/img/emoji/camera.png differ diff --git a/ui/img/emoji/cancer.png b/ui/img/emoji/cancer.png new file mode 100644 index 0000000..ea43a4a Binary files /dev/null and b/ui/img/emoji/cancer.png differ diff --git a/ui/img/emoji/candy.png b/ui/img/emoji/candy.png new file mode 100644 index 0000000..33722f2 Binary files /dev/null and b/ui/img/emoji/candy.png differ diff --git a/ui/img/emoji/capital_abcd.png b/ui/img/emoji/capital_abcd.png new file mode 100644 index 0000000..ffc0cba Binary files /dev/null and b/ui/img/emoji/capital_abcd.png differ diff --git a/ui/img/emoji/capricorn.png b/ui/img/emoji/capricorn.png new file mode 100644 index 0000000..f2044e7 Binary files /dev/null and b/ui/img/emoji/capricorn.png differ diff --git a/ui/img/emoji/car.png b/ui/img/emoji/car.png new file mode 100644 index 0000000..d70a2f0 Binary files /dev/null and b/ui/img/emoji/car.png differ diff --git a/ui/img/emoji/card_index.png b/ui/img/emoji/card_index.png new file mode 100644 index 0000000..374e94e Binary files /dev/null and b/ui/img/emoji/card_index.png differ diff --git a/ui/img/emoji/carousel_horse.png b/ui/img/emoji/carousel_horse.png new file mode 100644 index 0000000..765d2c0 Binary files /dev/null and b/ui/img/emoji/carousel_horse.png differ diff --git a/ui/img/emoji/cat.png b/ui/img/emoji/cat.png new file mode 100644 index 0000000..09b9ef7 Binary files /dev/null and b/ui/img/emoji/cat.png differ diff --git a/ui/img/emoji/cat2.png b/ui/img/emoji/cat2.png new file mode 100644 index 0000000..6dbc4c7 Binary files /dev/null and b/ui/img/emoji/cat2.png differ diff --git a/ui/img/emoji/cd.png b/ui/img/emoji/cd.png new file mode 100644 index 0000000..baff835 Binary files /dev/null and b/ui/img/emoji/cd.png differ diff --git a/ui/img/emoji/chart.png b/ui/img/emoji/chart.png new file mode 100644 index 0000000..ac2c4bb Binary files /dev/null and b/ui/img/emoji/chart.png differ diff --git a/ui/img/emoji/chart_with_downwards_trend.png b/ui/img/emoji/chart_with_downwards_trend.png new file mode 100644 index 0000000..cb0d2a1 Binary files /dev/null and b/ui/img/emoji/chart_with_downwards_trend.png differ diff --git a/ui/img/emoji/chart_with_upwards_trend.png b/ui/img/emoji/chart_with_upwards_trend.png new file mode 100644 index 0000000..7c66745 Binary files /dev/null and b/ui/img/emoji/chart_with_upwards_trend.png differ diff --git a/ui/img/emoji/checkered_flag.png b/ui/img/emoji/checkered_flag.png new file mode 100644 index 0000000..ead4a68 Binary files /dev/null and b/ui/img/emoji/checkered_flag.png differ diff --git a/ui/img/emoji/cherries.png b/ui/img/emoji/cherries.png new file mode 100644 index 0000000..8d3e044 Binary files /dev/null and b/ui/img/emoji/cherries.png differ diff --git a/ui/img/emoji/cherry_blossom.png b/ui/img/emoji/cherry_blossom.png new file mode 100644 index 0000000..e031554 Binary files /dev/null and b/ui/img/emoji/cherry_blossom.png differ diff --git a/ui/img/emoji/chestnut.png b/ui/img/emoji/chestnut.png new file mode 100644 index 0000000..066fb6b Binary files /dev/null and b/ui/img/emoji/chestnut.png differ diff --git a/ui/img/emoji/chicken.png b/ui/img/emoji/chicken.png new file mode 100644 index 0000000..6d25c0e Binary files /dev/null and b/ui/img/emoji/chicken.png differ diff --git a/ui/img/emoji/children_crossing.png b/ui/img/emoji/children_crossing.png new file mode 100644 index 0000000..b0302ae Binary files /dev/null and b/ui/img/emoji/children_crossing.png differ diff --git a/ui/img/emoji/chocolate_bar.png b/ui/img/emoji/chocolate_bar.png new file mode 100644 index 0000000..c7ec19d Binary files /dev/null and b/ui/img/emoji/chocolate_bar.png differ diff --git a/ui/img/emoji/christmas_tree.png b/ui/img/emoji/christmas_tree.png new file mode 100644 index 0000000..d813b95 Binary files /dev/null and b/ui/img/emoji/christmas_tree.png differ diff --git a/ui/img/emoji/church.png b/ui/img/emoji/church.png new file mode 100644 index 0000000..4c07c6b Binary files /dev/null and b/ui/img/emoji/church.png differ diff --git a/ui/img/emoji/cinema.png b/ui/img/emoji/cinema.png new file mode 100644 index 0000000..a990ccf Binary files /dev/null and b/ui/img/emoji/cinema.png differ diff --git a/ui/img/emoji/circus_tent.png b/ui/img/emoji/circus_tent.png new file mode 100644 index 0000000..4af8719 Binary files /dev/null and b/ui/img/emoji/circus_tent.png differ diff --git a/ui/img/emoji/city_sunrise.png b/ui/img/emoji/city_sunrise.png new file mode 100644 index 0000000..91ca2a4 Binary files /dev/null and b/ui/img/emoji/city_sunrise.png differ diff --git a/ui/img/emoji/city_sunset.png b/ui/img/emoji/city_sunset.png new file mode 100644 index 0000000..7cb178a Binary files /dev/null and b/ui/img/emoji/city_sunset.png differ diff --git a/ui/img/emoji/cl.png b/ui/img/emoji/cl.png new file mode 100644 index 0000000..15ac675 Binary files /dev/null and b/ui/img/emoji/cl.png differ diff --git a/ui/img/emoji/clap.png b/ui/img/emoji/clap.png new file mode 100644 index 0000000..d01c982 Binary files /dev/null and b/ui/img/emoji/clap.png differ diff --git a/ui/img/emoji/clapper.png b/ui/img/emoji/clapper.png new file mode 100644 index 0000000..4e1dc11 Binary files /dev/null and b/ui/img/emoji/clapper.png differ diff --git a/ui/img/emoji/clipboard.png b/ui/img/emoji/clipboard.png new file mode 100644 index 0000000..e2c74e6 Binary files /dev/null and b/ui/img/emoji/clipboard.png differ diff --git a/ui/img/emoji/clock1.png b/ui/img/emoji/clock1.png new file mode 100644 index 0000000..9174d4e Binary files /dev/null and b/ui/img/emoji/clock1.png differ diff --git a/ui/img/emoji/clock10.png b/ui/img/emoji/clock10.png new file mode 100644 index 0000000..39f590d Binary files /dev/null and b/ui/img/emoji/clock10.png differ diff --git a/ui/img/emoji/clock1030.png b/ui/img/emoji/clock1030.png new file mode 100644 index 0000000..0483b30 Binary files /dev/null and b/ui/img/emoji/clock1030.png differ diff --git a/ui/img/emoji/clock11.png b/ui/img/emoji/clock11.png new file mode 100644 index 0000000..ddb53fa Binary files /dev/null and b/ui/img/emoji/clock11.png differ diff --git a/ui/img/emoji/clock1130.png b/ui/img/emoji/clock1130.png new file mode 100644 index 0000000..415999e Binary files /dev/null and b/ui/img/emoji/clock1130.png differ diff --git a/ui/img/emoji/clock12.png b/ui/img/emoji/clock12.png new file mode 100644 index 0000000..87b1328 Binary files /dev/null and b/ui/img/emoji/clock12.png differ diff --git a/ui/img/emoji/clock1230.png b/ui/img/emoji/clock1230.png new file mode 100644 index 0000000..a652715 Binary files /dev/null and b/ui/img/emoji/clock1230.png differ diff --git a/ui/img/emoji/clock130.png b/ui/img/emoji/clock130.png new file mode 100644 index 0000000..90ea5b9 Binary files /dev/null and b/ui/img/emoji/clock130.png differ diff --git a/ui/img/emoji/clock2.png b/ui/img/emoji/clock2.png new file mode 100644 index 0000000..65b3b3a Binary files /dev/null and b/ui/img/emoji/clock2.png differ diff --git a/ui/img/emoji/clock230.png b/ui/img/emoji/clock230.png new file mode 100644 index 0000000..f12c691 Binary files /dev/null and b/ui/img/emoji/clock230.png differ diff --git a/ui/img/emoji/clock3.png b/ui/img/emoji/clock3.png new file mode 100644 index 0000000..3e44d64 Binary files /dev/null and b/ui/img/emoji/clock3.png differ diff --git a/ui/img/emoji/clock330.png b/ui/img/emoji/clock330.png new file mode 100644 index 0000000..1dc9628 Binary files /dev/null and b/ui/img/emoji/clock330.png differ diff --git a/ui/img/emoji/clock4.png b/ui/img/emoji/clock4.png new file mode 100644 index 0000000..948ed1a Binary files /dev/null and b/ui/img/emoji/clock4.png differ diff --git a/ui/img/emoji/clock430.png b/ui/img/emoji/clock430.png new file mode 100644 index 0000000..5d6b16a Binary files /dev/null and b/ui/img/emoji/clock430.png differ diff --git a/ui/img/emoji/clock5.png b/ui/img/emoji/clock5.png new file mode 100644 index 0000000..b010b4f Binary files /dev/null and b/ui/img/emoji/clock5.png differ diff --git a/ui/img/emoji/clock530.png b/ui/img/emoji/clock530.png new file mode 100644 index 0000000..e08d4ad Binary files /dev/null and b/ui/img/emoji/clock530.png differ diff --git a/ui/img/emoji/clock6.png b/ui/img/emoji/clock6.png new file mode 100644 index 0000000..76bf8cf Binary files /dev/null and b/ui/img/emoji/clock6.png differ diff --git a/ui/img/emoji/clock630.png b/ui/img/emoji/clock630.png new file mode 100644 index 0000000..46f0681 Binary files /dev/null and b/ui/img/emoji/clock630.png differ diff --git a/ui/img/emoji/clock7.png b/ui/img/emoji/clock7.png new file mode 100644 index 0000000..d48f645 Binary files /dev/null and b/ui/img/emoji/clock7.png differ diff --git a/ui/img/emoji/clock730.png b/ui/img/emoji/clock730.png new file mode 100644 index 0000000..f2807de Binary files /dev/null and b/ui/img/emoji/clock730.png differ diff --git a/ui/img/emoji/clock8.png b/ui/img/emoji/clock8.png new file mode 100644 index 0000000..74c770d Binary files /dev/null and b/ui/img/emoji/clock8.png differ diff --git a/ui/img/emoji/clock830.png b/ui/img/emoji/clock830.png new file mode 100644 index 0000000..f58f3da Binary files /dev/null and b/ui/img/emoji/clock830.png differ diff --git a/ui/img/emoji/clock9.png b/ui/img/emoji/clock9.png new file mode 100644 index 0000000..f009d14 Binary files /dev/null and b/ui/img/emoji/clock9.png differ diff --git a/ui/img/emoji/clock930.png b/ui/img/emoji/clock930.png new file mode 100644 index 0000000..fd35221 Binary files /dev/null and b/ui/img/emoji/clock930.png differ diff --git a/ui/img/emoji/closed_book.png b/ui/img/emoji/closed_book.png new file mode 100644 index 0000000..484029c Binary files /dev/null and b/ui/img/emoji/closed_book.png differ diff --git a/ui/img/emoji/closed_lock_with_key.png b/ui/img/emoji/closed_lock_with_key.png new file mode 100644 index 0000000..e6fdf6c Binary files /dev/null and b/ui/img/emoji/closed_lock_with_key.png differ diff --git a/ui/img/emoji/closed_umbrella.png b/ui/img/emoji/closed_umbrella.png new file mode 100644 index 0000000..0b719f0 Binary files /dev/null and b/ui/img/emoji/closed_umbrella.png differ diff --git a/ui/img/emoji/cloud.png b/ui/img/emoji/cloud.png new file mode 100644 index 0000000..b31c08c Binary files /dev/null and b/ui/img/emoji/cloud.png differ diff --git a/ui/img/emoji/clubs.png b/ui/img/emoji/clubs.png new file mode 100644 index 0000000..bfab536 Binary files /dev/null and b/ui/img/emoji/clubs.png differ diff --git a/ui/img/emoji/cn.png b/ui/img/emoji/cn.png new file mode 100644 index 0000000..b30dcc5 Binary files /dev/null and b/ui/img/emoji/cn.png differ diff --git a/ui/img/emoji/cocktail.png b/ui/img/emoji/cocktail.png new file mode 100644 index 0000000..28b45ea Binary files /dev/null and b/ui/img/emoji/cocktail.png differ diff --git a/ui/img/emoji/coffee.png b/ui/img/emoji/coffee.png new file mode 100644 index 0000000..57e1adc Binary files /dev/null and b/ui/img/emoji/coffee.png differ diff --git a/ui/img/emoji/cold_sweat.png b/ui/img/emoji/cold_sweat.png new file mode 100644 index 0000000..b9e39bc Binary files /dev/null and b/ui/img/emoji/cold_sweat.png differ diff --git a/ui/img/emoji/collision.png b/ui/img/emoji/collision.png new file mode 100644 index 0000000..9d5bd04 Binary files /dev/null and b/ui/img/emoji/collision.png differ diff --git a/ui/img/emoji/computer.png b/ui/img/emoji/computer.png new file mode 100644 index 0000000..d4d2687 Binary files /dev/null and b/ui/img/emoji/computer.png differ diff --git a/ui/img/emoji/confetti_ball.png b/ui/img/emoji/confetti_ball.png new file mode 100644 index 0000000..bd293e3 Binary files /dev/null and b/ui/img/emoji/confetti_ball.png differ diff --git a/ui/img/emoji/confounded.png b/ui/img/emoji/confounded.png new file mode 100644 index 0000000..762c376 Binary files /dev/null and b/ui/img/emoji/confounded.png differ diff --git a/ui/img/emoji/confused.png b/ui/img/emoji/confused.png new file mode 100644 index 0000000..8dc494d Binary files /dev/null and b/ui/img/emoji/confused.png differ diff --git a/ui/img/emoji/congratulations.png b/ui/img/emoji/congratulations.png new file mode 100644 index 0000000..85814e3 Binary files /dev/null and b/ui/img/emoji/congratulations.png differ diff --git a/ui/img/emoji/construction.png b/ui/img/emoji/construction.png new file mode 100644 index 0000000..523e9f1 Binary files /dev/null and b/ui/img/emoji/construction.png differ diff --git a/ui/img/emoji/construction_worker.png b/ui/img/emoji/construction_worker.png new file mode 100644 index 0000000..4d64860 Binary files /dev/null and b/ui/img/emoji/construction_worker.png differ diff --git a/ui/img/emoji/convenience_store.png b/ui/img/emoji/convenience_store.png new file mode 100644 index 0000000..671696c Binary files /dev/null and b/ui/img/emoji/convenience_store.png differ diff --git a/ui/img/emoji/cookie.png b/ui/img/emoji/cookie.png new file mode 100644 index 0000000..653edb2 Binary files /dev/null and b/ui/img/emoji/cookie.png differ diff --git a/ui/img/emoji/cool.png b/ui/img/emoji/cool.png new file mode 100644 index 0000000..937dcd7 Binary files /dev/null and b/ui/img/emoji/cool.png differ diff --git a/ui/img/emoji/cop.png b/ui/img/emoji/cop.png new file mode 100644 index 0000000..43a5a84 Binary files /dev/null and b/ui/img/emoji/cop.png differ diff --git a/ui/img/emoji/copyright.png b/ui/img/emoji/copyright.png new file mode 100644 index 0000000..38493c3 Binary files /dev/null and b/ui/img/emoji/copyright.png differ diff --git a/ui/img/emoji/corn.png b/ui/img/emoji/corn.png new file mode 100644 index 0000000..fe5d8b1 Binary files /dev/null and b/ui/img/emoji/corn.png differ diff --git a/ui/img/emoji/couple.png b/ui/img/emoji/couple.png new file mode 100644 index 0000000..9e51f40 Binary files /dev/null and b/ui/img/emoji/couple.png differ diff --git a/ui/img/emoji/couple_with_heart.png b/ui/img/emoji/couple_with_heart.png new file mode 100644 index 0000000..c503f40 Binary files /dev/null and b/ui/img/emoji/couple_with_heart.png differ diff --git a/ui/img/emoji/couplekiss.png b/ui/img/emoji/couplekiss.png new file mode 100644 index 0000000..d027908 Binary files /dev/null and b/ui/img/emoji/couplekiss.png differ diff --git a/ui/img/emoji/cow.png b/ui/img/emoji/cow.png new file mode 100644 index 0000000..12e1ab6 Binary files /dev/null and b/ui/img/emoji/cow.png differ diff --git a/ui/img/emoji/cow2.png b/ui/img/emoji/cow2.png new file mode 100644 index 0000000..594c921 Binary files /dev/null and b/ui/img/emoji/cow2.png differ diff --git a/ui/img/emoji/credit_card.png b/ui/img/emoji/credit_card.png new file mode 100644 index 0000000..be1c1dd Binary files /dev/null and b/ui/img/emoji/credit_card.png differ diff --git a/ui/img/emoji/crocodile.png b/ui/img/emoji/crocodile.png new file mode 100644 index 0000000..7435d5a Binary files /dev/null and b/ui/img/emoji/crocodile.png differ diff --git a/ui/img/emoji/crossed_flags.png b/ui/img/emoji/crossed_flags.png new file mode 100644 index 0000000..2397bcd Binary files /dev/null and b/ui/img/emoji/crossed_flags.png differ diff --git a/ui/img/emoji/crown.png b/ui/img/emoji/crown.png new file mode 100644 index 0000000..39da1d5 Binary files /dev/null and b/ui/img/emoji/crown.png differ diff --git a/ui/img/emoji/cry.png b/ui/img/emoji/cry.png new file mode 100644 index 0000000..6d0d9af Binary files /dev/null and b/ui/img/emoji/cry.png differ diff --git a/ui/img/emoji/crying_cat_face.png b/ui/img/emoji/crying_cat_face.png new file mode 100644 index 0000000..42d4c27 Binary files /dev/null and b/ui/img/emoji/crying_cat_face.png differ diff --git a/ui/img/emoji/crystal_ball.png b/ui/img/emoji/crystal_ball.png new file mode 100644 index 0000000..6d2c6c4 Binary files /dev/null and b/ui/img/emoji/crystal_ball.png differ diff --git a/ui/img/emoji/cupid.png b/ui/img/emoji/cupid.png new file mode 100644 index 0000000..4987284 Binary files /dev/null and b/ui/img/emoji/cupid.png differ diff --git a/ui/img/emoji/curly_loop.png b/ui/img/emoji/curly_loop.png new file mode 100644 index 0000000..7dd841d Binary files /dev/null and b/ui/img/emoji/curly_loop.png differ diff --git a/ui/img/emoji/currency_exchange.png b/ui/img/emoji/currency_exchange.png new file mode 100644 index 0000000..6ebebe7 Binary files /dev/null and b/ui/img/emoji/currency_exchange.png differ diff --git a/ui/img/emoji/curry.png b/ui/img/emoji/curry.png new file mode 100644 index 0000000..7983c70 Binary files /dev/null and b/ui/img/emoji/curry.png differ diff --git a/ui/img/emoji/custard.png b/ui/img/emoji/custard.png new file mode 100644 index 0000000..9f843b4 Binary files /dev/null and b/ui/img/emoji/custard.png differ diff --git a/ui/img/emoji/customs.png b/ui/img/emoji/customs.png new file mode 100644 index 0000000..92691e3 Binary files /dev/null and b/ui/img/emoji/customs.png differ diff --git a/ui/img/emoji/cyclone.png b/ui/img/emoji/cyclone.png new file mode 100644 index 0000000..5fd2e45 Binary files /dev/null and b/ui/img/emoji/cyclone.png differ diff --git a/ui/img/emoji/dancer.png b/ui/img/emoji/dancer.png new file mode 100644 index 0000000..7a7bf59 Binary files /dev/null and b/ui/img/emoji/dancer.png differ diff --git a/ui/img/emoji/dancers.png b/ui/img/emoji/dancers.png new file mode 100644 index 0000000..2dfb451 Binary files /dev/null and b/ui/img/emoji/dancers.png differ diff --git a/ui/img/emoji/dango.png b/ui/img/emoji/dango.png new file mode 100644 index 0000000..2d042ae Binary files /dev/null and b/ui/img/emoji/dango.png differ diff --git a/ui/img/emoji/dart.png b/ui/img/emoji/dart.png new file mode 100644 index 0000000..5f16864 Binary files /dev/null and b/ui/img/emoji/dart.png differ diff --git a/ui/img/emoji/dash.png b/ui/img/emoji/dash.png new file mode 100644 index 0000000..dc2c0a8 Binary files /dev/null and b/ui/img/emoji/dash.png differ diff --git a/ui/img/emoji/date.png b/ui/img/emoji/date.png new file mode 100644 index 0000000..6ad2efa Binary files /dev/null and b/ui/img/emoji/date.png differ diff --git a/ui/img/emoji/de.png b/ui/img/emoji/de.png new file mode 100644 index 0000000..16a2854 Binary files /dev/null and b/ui/img/emoji/de.png differ diff --git a/ui/img/emoji/deciduous_tree.png b/ui/img/emoji/deciduous_tree.png new file mode 100644 index 0000000..3fdf8c0 Binary files /dev/null and b/ui/img/emoji/deciduous_tree.png differ diff --git a/ui/img/emoji/department_store.png b/ui/img/emoji/department_store.png new file mode 100644 index 0000000..68d959c Binary files /dev/null and b/ui/img/emoji/department_store.png differ diff --git a/ui/img/emoji/diamond_shape_with_a_dot_inside.png b/ui/img/emoji/diamond_shape_with_a_dot_inside.png new file mode 100644 index 0000000..dfd1098 Binary files /dev/null and b/ui/img/emoji/diamond_shape_with_a_dot_inside.png differ diff --git a/ui/img/emoji/diamonds.png b/ui/img/emoji/diamonds.png new file mode 100644 index 0000000..fe08277 Binary files /dev/null and b/ui/img/emoji/diamonds.png differ diff --git a/ui/img/emoji/disappointed.png b/ui/img/emoji/disappointed.png new file mode 100644 index 0000000..8255200 Binary files /dev/null and b/ui/img/emoji/disappointed.png differ diff --git a/ui/img/emoji/disappointed_relieved.png b/ui/img/emoji/disappointed_relieved.png new file mode 100644 index 0000000..fa5f9e7 Binary files /dev/null and b/ui/img/emoji/disappointed_relieved.png differ diff --git a/ui/img/emoji/dizzy.png b/ui/img/emoji/dizzy.png new file mode 100644 index 0000000..3702b61 Binary files /dev/null and b/ui/img/emoji/dizzy.png differ diff --git a/ui/img/emoji/dizzy_face.png b/ui/img/emoji/dizzy_face.png new file mode 100644 index 0000000..8001d6f Binary files /dev/null and b/ui/img/emoji/dizzy_face.png differ diff --git a/ui/img/emoji/do_not_litter.png b/ui/img/emoji/do_not_litter.png new file mode 100644 index 0000000..38c7ae7 Binary files /dev/null and b/ui/img/emoji/do_not_litter.png differ diff --git a/ui/img/emoji/dog.png b/ui/img/emoji/dog.png new file mode 100644 index 0000000..389a02b Binary files /dev/null and b/ui/img/emoji/dog.png differ diff --git a/ui/img/emoji/dog2.png b/ui/img/emoji/dog2.png new file mode 100644 index 0000000..c7f6a24 Binary files /dev/null and b/ui/img/emoji/dog2.png differ diff --git a/ui/img/emoji/dollar.png b/ui/img/emoji/dollar.png new file mode 100644 index 0000000..63de884 Binary files /dev/null and b/ui/img/emoji/dollar.png differ diff --git a/ui/img/emoji/dolls.png b/ui/img/emoji/dolls.png new file mode 100644 index 0000000..47ce339 Binary files /dev/null and b/ui/img/emoji/dolls.png differ diff --git a/ui/img/emoji/dolphin.png b/ui/img/emoji/dolphin.png new file mode 100644 index 0000000..9326077 Binary files /dev/null and b/ui/img/emoji/dolphin.png differ diff --git a/ui/img/emoji/donut.png b/ui/img/emoji/donut.png new file mode 100644 index 0000000..ccf8691 Binary files /dev/null and b/ui/img/emoji/donut.png differ diff --git a/ui/img/emoji/door.png b/ui/img/emoji/door.png new file mode 100644 index 0000000..83c819a Binary files /dev/null and b/ui/img/emoji/door.png differ diff --git a/ui/img/emoji/doughnut.png b/ui/img/emoji/doughnut.png new file mode 100644 index 0000000..ccf8691 Binary files /dev/null and b/ui/img/emoji/doughnut.png differ diff --git a/ui/img/emoji/dragon.png b/ui/img/emoji/dragon.png new file mode 100644 index 0000000..88d4784 Binary files /dev/null and b/ui/img/emoji/dragon.png differ diff --git a/ui/img/emoji/dragon_face.png b/ui/img/emoji/dragon_face.png new file mode 100644 index 0000000..e5e556b Binary files /dev/null and b/ui/img/emoji/dragon_face.png differ diff --git a/ui/img/emoji/dress.png b/ui/img/emoji/dress.png new file mode 100644 index 0000000..6434e2e Binary files /dev/null and b/ui/img/emoji/dress.png differ diff --git a/ui/img/emoji/dromedary_camel.png b/ui/img/emoji/dromedary_camel.png new file mode 100644 index 0000000..c8c7b9f Binary files /dev/null and b/ui/img/emoji/dromedary_camel.png differ diff --git a/ui/img/emoji/droplet.png b/ui/img/emoji/droplet.png new file mode 100644 index 0000000..cae7f49 Binary files /dev/null and b/ui/img/emoji/droplet.png differ diff --git a/ui/img/emoji/dvd.png b/ui/img/emoji/dvd.png new file mode 100644 index 0000000..363c83d Binary files /dev/null and b/ui/img/emoji/dvd.png differ diff --git a/ui/img/emoji/e-mail.png b/ui/img/emoji/e-mail.png new file mode 100644 index 0000000..176a8e1 Binary files /dev/null and b/ui/img/emoji/e-mail.png differ diff --git a/ui/img/emoji/ear.png b/ui/img/emoji/ear.png new file mode 100644 index 0000000..2bbbf10 Binary files /dev/null and b/ui/img/emoji/ear.png differ diff --git a/ui/img/emoji/ear_of_rice.png b/ui/img/emoji/ear_of_rice.png new file mode 100644 index 0000000..a9bba5c Binary files /dev/null and b/ui/img/emoji/ear_of_rice.png differ diff --git a/ui/img/emoji/earth_africa.png b/ui/img/emoji/earth_africa.png new file mode 100644 index 0000000..44ce5ec Binary files /dev/null and b/ui/img/emoji/earth_africa.png differ diff --git a/ui/img/emoji/earth_americas.png b/ui/img/emoji/earth_americas.png new file mode 100644 index 0000000..97d7176 Binary files /dev/null and b/ui/img/emoji/earth_americas.png differ diff --git a/ui/img/emoji/earth_asia.png b/ui/img/emoji/earth_asia.png new file mode 100644 index 0000000..95ec357 Binary files /dev/null and b/ui/img/emoji/earth_asia.png differ diff --git a/ui/img/emoji/egg.png b/ui/img/emoji/egg.png new file mode 100644 index 0000000..c3de6ae Binary files /dev/null and b/ui/img/emoji/egg.png differ diff --git a/ui/img/emoji/eggplant.png b/ui/img/emoji/eggplant.png new file mode 100644 index 0000000..66f25fc Binary files /dev/null and b/ui/img/emoji/eggplant.png differ diff --git a/ui/img/emoji/eight.png b/ui/img/emoji/eight.png new file mode 100644 index 0000000..7bdb422 Binary files /dev/null and b/ui/img/emoji/eight.png differ diff --git a/ui/img/emoji/eight_pointed_black_star.png b/ui/img/emoji/eight_pointed_black_star.png new file mode 100644 index 0000000..2420a77 Binary files /dev/null and b/ui/img/emoji/eight_pointed_black_star.png differ diff --git a/ui/img/emoji/eight_spoked_asterisk.png b/ui/img/emoji/eight_spoked_asterisk.png new file mode 100644 index 0000000..946a203 Binary files /dev/null and b/ui/img/emoji/eight_spoked_asterisk.png differ diff --git a/ui/img/emoji/electric_plug.png b/ui/img/emoji/electric_plug.png new file mode 100644 index 0000000..2837bab Binary files /dev/null and b/ui/img/emoji/electric_plug.png differ diff --git a/ui/img/emoji/elephant.png b/ui/img/emoji/elephant.png new file mode 100644 index 0000000..5ca0457 Binary files /dev/null and b/ui/img/emoji/elephant.png differ diff --git a/ui/img/emoji/email.png b/ui/img/emoji/email.png new file mode 100644 index 0000000..0e01fd5 Binary files /dev/null and b/ui/img/emoji/email.png differ diff --git a/ui/img/emoji/end.png b/ui/img/emoji/end.png new file mode 100644 index 0000000..61a4399 Binary files /dev/null and b/ui/img/emoji/end.png differ diff --git a/ui/img/emoji/envelope.png b/ui/img/emoji/envelope.png new file mode 100644 index 0000000..3631861 Binary files /dev/null and b/ui/img/emoji/envelope.png differ diff --git a/ui/img/emoji/es.png b/ui/img/emoji/es.png new file mode 100644 index 0000000..71b30bf Binary files /dev/null and b/ui/img/emoji/es.png differ diff --git a/ui/img/emoji/euro.png b/ui/img/emoji/euro.png new file mode 100644 index 0000000..1c5904b Binary files /dev/null and b/ui/img/emoji/euro.png differ diff --git a/ui/img/emoji/european_castle.png b/ui/img/emoji/european_castle.png new file mode 100644 index 0000000..8229b8a Binary files /dev/null and b/ui/img/emoji/european_castle.png differ diff --git a/ui/img/emoji/european_post_office.png b/ui/img/emoji/european_post_office.png new file mode 100644 index 0000000..0f65b14 Binary files /dev/null and b/ui/img/emoji/european_post_office.png differ diff --git a/ui/img/emoji/evergreen_tree.png b/ui/img/emoji/evergreen_tree.png new file mode 100644 index 0000000..ae8ad10 Binary files /dev/null and b/ui/img/emoji/evergreen_tree.png differ diff --git a/ui/img/emoji/exclamation.png b/ui/img/emoji/exclamation.png new file mode 100644 index 0000000..77bbdea Binary files /dev/null and b/ui/img/emoji/exclamation.png differ diff --git a/ui/img/emoji/expressionless.png b/ui/img/emoji/expressionless.png new file mode 100644 index 0000000..913ff4e Binary files /dev/null and b/ui/img/emoji/expressionless.png differ diff --git a/ui/img/emoji/eyeglasses.png b/ui/img/emoji/eyeglasses.png new file mode 100644 index 0000000..a3cf75a Binary files /dev/null and b/ui/img/emoji/eyeglasses.png differ diff --git a/ui/img/emoji/eyes.png b/ui/img/emoji/eyes.png new file mode 100644 index 0000000..1ac24a6 Binary files /dev/null and b/ui/img/emoji/eyes.png differ diff --git a/ui/img/emoji/facepunch.png b/ui/img/emoji/facepunch.png new file mode 100644 index 0000000..277047b Binary files /dev/null and b/ui/img/emoji/facepunch.png differ diff --git a/ui/img/emoji/factory.png b/ui/img/emoji/factory.png new file mode 100644 index 0000000..6404634 Binary files /dev/null and b/ui/img/emoji/factory.png differ diff --git a/ui/img/emoji/fallen_leaf.png b/ui/img/emoji/fallen_leaf.png new file mode 100644 index 0000000..d49f9c1 Binary files /dev/null and b/ui/img/emoji/fallen_leaf.png differ diff --git a/ui/img/emoji/family.png b/ui/img/emoji/family.png new file mode 100644 index 0000000..b4b365f Binary files /dev/null and b/ui/img/emoji/family.png differ diff --git a/ui/img/emoji/fast_forward.png b/ui/img/emoji/fast_forward.png new file mode 100644 index 0000000..8830e14 Binary files /dev/null and b/ui/img/emoji/fast_forward.png differ diff --git a/ui/img/emoji/fax.png b/ui/img/emoji/fax.png new file mode 100644 index 0000000..62be2c9 Binary files /dev/null and b/ui/img/emoji/fax.png differ diff --git a/ui/img/emoji/fearful.png b/ui/img/emoji/fearful.png new file mode 100644 index 0000000..513fce4 Binary files /dev/null and b/ui/img/emoji/fearful.png differ diff --git a/ui/img/emoji/feelsgood.png b/ui/img/emoji/feelsgood.png new file mode 100644 index 0000000..361f969 Binary files /dev/null and b/ui/img/emoji/feelsgood.png differ diff --git a/ui/img/emoji/feet.png b/ui/img/emoji/feet.png new file mode 100644 index 0000000..1b0147b Binary files /dev/null and b/ui/img/emoji/feet.png differ diff --git a/ui/img/emoji/ferris_wheel.png b/ui/img/emoji/ferris_wheel.png new file mode 100644 index 0000000..54a1dcf Binary files /dev/null and b/ui/img/emoji/ferris_wheel.png differ diff --git a/ui/img/emoji/file_folder.png b/ui/img/emoji/file_folder.png new file mode 100644 index 0000000..4d8bebf Binary files /dev/null and b/ui/img/emoji/file_folder.png differ diff --git a/ui/img/emoji/finnadie.png b/ui/img/emoji/finnadie.png new file mode 100644 index 0000000..bfc5a0d Binary files /dev/null and b/ui/img/emoji/finnadie.png differ diff --git a/ui/img/emoji/fire.png b/ui/img/emoji/fire.png new file mode 100644 index 0000000..f2a3149 Binary files /dev/null and b/ui/img/emoji/fire.png differ diff --git a/ui/img/emoji/fire_engine.png b/ui/img/emoji/fire_engine.png new file mode 100644 index 0000000..9e6c59c Binary files /dev/null and b/ui/img/emoji/fire_engine.png differ diff --git a/ui/img/emoji/fireworks.png b/ui/img/emoji/fireworks.png new file mode 100644 index 0000000..b4eccd5 Binary files /dev/null and b/ui/img/emoji/fireworks.png differ diff --git a/ui/img/emoji/first_quarter_moon.png b/ui/img/emoji/first_quarter_moon.png new file mode 100644 index 0000000..f38c236 Binary files /dev/null and b/ui/img/emoji/first_quarter_moon.png differ diff --git a/ui/img/emoji/first_quarter_moon_with_face.png b/ui/img/emoji/first_quarter_moon_with_face.png new file mode 100644 index 0000000..85ae2ce Binary files /dev/null and b/ui/img/emoji/first_quarter_moon_with_face.png differ diff --git a/ui/img/emoji/fish.png b/ui/img/emoji/fish.png new file mode 100644 index 0000000..90bdda2 Binary files /dev/null and b/ui/img/emoji/fish.png differ diff --git a/ui/img/emoji/fish_cake.png b/ui/img/emoji/fish_cake.png new file mode 100644 index 0000000..a8f2261 Binary files /dev/null and b/ui/img/emoji/fish_cake.png differ diff --git a/ui/img/emoji/fishing_pole_and_fish.png b/ui/img/emoji/fishing_pole_and_fish.png new file mode 100644 index 0000000..d84609c Binary files /dev/null and b/ui/img/emoji/fishing_pole_and_fish.png differ diff --git a/ui/img/emoji/fist.png b/ui/img/emoji/fist.png new file mode 100644 index 0000000..ecc8874 Binary files /dev/null and b/ui/img/emoji/fist.png differ diff --git a/ui/img/emoji/five.png b/ui/img/emoji/five.png new file mode 100644 index 0000000..794321a Binary files /dev/null and b/ui/img/emoji/five.png differ diff --git a/ui/img/emoji/flags.png b/ui/img/emoji/flags.png new file mode 100644 index 0000000..540164e Binary files /dev/null and b/ui/img/emoji/flags.png differ diff --git a/ui/img/emoji/flashlight.png b/ui/img/emoji/flashlight.png new file mode 100644 index 0000000..215940a Binary files /dev/null and b/ui/img/emoji/flashlight.png differ diff --git a/ui/img/emoji/floppy_disk.png b/ui/img/emoji/floppy_disk.png new file mode 100644 index 0000000..4ad5631 Binary files /dev/null and b/ui/img/emoji/floppy_disk.png differ diff --git a/ui/img/emoji/flower_playing_cards.png b/ui/img/emoji/flower_playing_cards.png new file mode 100644 index 0000000..cc46a6a Binary files /dev/null and b/ui/img/emoji/flower_playing_cards.png differ diff --git a/ui/img/emoji/flushed.png b/ui/img/emoji/flushed.png new file mode 100644 index 0000000..74b78c9 Binary files /dev/null and b/ui/img/emoji/flushed.png differ diff --git a/ui/img/emoji/foggy.png b/ui/img/emoji/foggy.png new file mode 100644 index 0000000..3c7b8b0 Binary files /dev/null and b/ui/img/emoji/foggy.png differ diff --git a/ui/img/emoji/football.png b/ui/img/emoji/football.png new file mode 100644 index 0000000..0e4e168 Binary files /dev/null and b/ui/img/emoji/football.png differ diff --git a/ui/img/emoji/fork_and_knife.png b/ui/img/emoji/fork_and_knife.png new file mode 100644 index 0000000..8ba4bc6 Binary files /dev/null and b/ui/img/emoji/fork_and_knife.png differ diff --git a/ui/img/emoji/fountain.png b/ui/img/emoji/fountain.png new file mode 100644 index 0000000..da126e6 Binary files /dev/null and b/ui/img/emoji/fountain.png differ diff --git a/ui/img/emoji/four.png b/ui/img/emoji/four.png new file mode 100644 index 0000000..14782ba Binary files /dev/null and b/ui/img/emoji/four.png differ diff --git a/ui/img/emoji/four_leaf_clover.png b/ui/img/emoji/four_leaf_clover.png new file mode 100644 index 0000000..f2014be Binary files /dev/null and b/ui/img/emoji/four_leaf_clover.png differ diff --git a/ui/img/emoji/fr.png b/ui/img/emoji/fr.png new file mode 100644 index 0000000..6311c91 Binary files /dev/null and b/ui/img/emoji/fr.png differ diff --git a/ui/img/emoji/free.png b/ui/img/emoji/free.png new file mode 100644 index 0000000..c886cf2 Binary files /dev/null and b/ui/img/emoji/free.png differ diff --git a/ui/img/emoji/fried_shrimp.png b/ui/img/emoji/fried_shrimp.png new file mode 100644 index 0000000..c8c284b Binary files /dev/null and b/ui/img/emoji/fried_shrimp.png differ diff --git a/ui/img/emoji/fries.png b/ui/img/emoji/fries.png new file mode 100644 index 0000000..cfef669 Binary files /dev/null and b/ui/img/emoji/fries.png differ diff --git a/ui/img/emoji/frog.png b/ui/img/emoji/frog.png new file mode 100644 index 0000000..cfe11b1 Binary files /dev/null and b/ui/img/emoji/frog.png differ diff --git a/ui/img/emoji/frowning.png b/ui/img/emoji/frowning.png new file mode 100644 index 0000000..487b770 Binary files /dev/null and b/ui/img/emoji/frowning.png differ diff --git a/ui/img/emoji/fu.png b/ui/img/emoji/fu.png new file mode 100644 index 0000000..61a3fee Binary files /dev/null and b/ui/img/emoji/fu.png differ diff --git a/ui/img/emoji/fuelpump.png b/ui/img/emoji/fuelpump.png new file mode 100644 index 0000000..54c29ae Binary files /dev/null and b/ui/img/emoji/fuelpump.png differ diff --git a/ui/img/emoji/full_moon.png b/ui/img/emoji/full_moon.png new file mode 100644 index 0000000..8ff657a Binary files /dev/null and b/ui/img/emoji/full_moon.png differ diff --git a/ui/img/emoji/full_moon_with_face.png b/ui/img/emoji/full_moon_with_face.png new file mode 100644 index 0000000..d42b3f0 Binary files /dev/null and b/ui/img/emoji/full_moon_with_face.png differ diff --git a/ui/img/emoji/game_die.png b/ui/img/emoji/game_die.png new file mode 100644 index 0000000..cff2bd8 Binary files /dev/null and b/ui/img/emoji/game_die.png differ diff --git a/ui/img/emoji/gb.png b/ui/img/emoji/gb.png new file mode 100644 index 0000000..2a62c7a Binary files /dev/null and b/ui/img/emoji/gb.png differ diff --git a/ui/img/emoji/gem.png b/ui/img/emoji/gem.png new file mode 100644 index 0000000..8a5d8da Binary files /dev/null and b/ui/img/emoji/gem.png differ diff --git a/ui/img/emoji/gemini.png b/ui/img/emoji/gemini.png new file mode 100644 index 0000000..d926f6e Binary files /dev/null and b/ui/img/emoji/gemini.png differ diff --git a/ui/img/emoji/ghost.png b/ui/img/emoji/ghost.png new file mode 100644 index 0000000..671dd0c Binary files /dev/null and b/ui/img/emoji/ghost.png differ diff --git a/ui/img/emoji/gift.png b/ui/img/emoji/gift.png new file mode 100644 index 0000000..552cfdc Binary files /dev/null and b/ui/img/emoji/gift.png differ diff --git a/ui/img/emoji/gift_heart.png b/ui/img/emoji/gift_heart.png new file mode 100644 index 0000000..f31c26a Binary files /dev/null and b/ui/img/emoji/gift_heart.png differ diff --git a/ui/img/emoji/girl.png b/ui/img/emoji/girl.png new file mode 100644 index 0000000..ea41269 Binary files /dev/null and b/ui/img/emoji/girl.png differ diff --git a/ui/img/emoji/globe_with_meridians.png b/ui/img/emoji/globe_with_meridians.png new file mode 100644 index 0000000..b198646 Binary files /dev/null and b/ui/img/emoji/globe_with_meridians.png differ diff --git a/ui/img/emoji/goat.png b/ui/img/emoji/goat.png new file mode 100644 index 0000000..4be9cf3 Binary files /dev/null and b/ui/img/emoji/goat.png differ diff --git a/ui/img/emoji/goberserk.png b/ui/img/emoji/goberserk.png new file mode 100644 index 0000000..59a742a Binary files /dev/null and b/ui/img/emoji/goberserk.png differ diff --git a/ui/img/emoji/godmode.png b/ui/img/emoji/godmode.png new file mode 100644 index 0000000..7e75ab2 Binary files /dev/null and b/ui/img/emoji/godmode.png differ diff --git a/ui/img/emoji/golf.png b/ui/img/emoji/golf.png new file mode 100644 index 0000000..cba2116 Binary files /dev/null and b/ui/img/emoji/golf.png differ diff --git a/ui/img/emoji/grapes.png b/ui/img/emoji/grapes.png new file mode 100644 index 0000000..0f9f007 Binary files /dev/null and b/ui/img/emoji/grapes.png differ diff --git a/ui/img/emoji/green_apple.png b/ui/img/emoji/green_apple.png new file mode 100644 index 0000000..337205c Binary files /dev/null and b/ui/img/emoji/green_apple.png differ diff --git a/ui/img/emoji/green_book.png b/ui/img/emoji/green_book.png new file mode 100644 index 0000000..e86651e Binary files /dev/null and b/ui/img/emoji/green_book.png differ diff --git a/ui/img/emoji/green_heart.png b/ui/img/emoji/green_heart.png new file mode 100644 index 0000000..7289cb8 Binary files /dev/null and b/ui/img/emoji/green_heart.png differ diff --git a/ui/img/emoji/grey_exclamation.png b/ui/img/emoji/grey_exclamation.png new file mode 100644 index 0000000..cf027dd Binary files /dev/null and b/ui/img/emoji/grey_exclamation.png differ diff --git a/ui/img/emoji/grey_question.png b/ui/img/emoji/grey_question.png new file mode 100644 index 0000000..fb97ba7 Binary files /dev/null and b/ui/img/emoji/grey_question.png differ diff --git a/ui/img/emoji/grimacing.png b/ui/img/emoji/grimacing.png new file mode 100644 index 0000000..1219ba7 Binary files /dev/null and b/ui/img/emoji/grimacing.png differ diff --git a/ui/img/emoji/grin.png b/ui/img/emoji/grin.png new file mode 100644 index 0000000..591cfce Binary files /dev/null and b/ui/img/emoji/grin.png differ diff --git a/ui/img/emoji/grinning.png b/ui/img/emoji/grinning.png new file mode 100644 index 0000000..7e812b7 Binary files /dev/null and b/ui/img/emoji/grinning.png differ diff --git a/ui/img/emoji/guardsman.png b/ui/img/emoji/guardsman.png new file mode 100644 index 0000000..b67b335 Binary files /dev/null and b/ui/img/emoji/guardsman.png differ diff --git a/ui/img/emoji/guitar.png b/ui/img/emoji/guitar.png new file mode 100644 index 0000000..2b7fa43 Binary files /dev/null and b/ui/img/emoji/guitar.png differ diff --git a/ui/img/emoji/gun.png b/ui/img/emoji/gun.png new file mode 100644 index 0000000..c49dc52 Binary files /dev/null and b/ui/img/emoji/gun.png differ diff --git a/ui/img/emoji/haircut.png b/ui/img/emoji/haircut.png new file mode 100644 index 0000000..902d273 Binary files /dev/null and b/ui/img/emoji/haircut.png differ diff --git a/ui/img/emoji/hamburger.png b/ui/img/emoji/hamburger.png new file mode 100644 index 0000000..9f1a3fd Binary files /dev/null and b/ui/img/emoji/hamburger.png differ diff --git a/ui/img/emoji/hammer.png b/ui/img/emoji/hammer.png new file mode 100644 index 0000000..482b1c7 Binary files /dev/null and b/ui/img/emoji/hammer.png differ diff --git a/ui/img/emoji/hamster.png b/ui/img/emoji/hamster.png new file mode 100644 index 0000000..addfd2e Binary files /dev/null and b/ui/img/emoji/hamster.png differ diff --git a/ui/img/emoji/hand.png b/ui/img/emoji/hand.png new file mode 100644 index 0000000..5e45c25 Binary files /dev/null and b/ui/img/emoji/hand.png differ diff --git a/ui/img/emoji/handbag.png b/ui/img/emoji/handbag.png new file mode 100644 index 0000000..d7adf04 Binary files /dev/null and b/ui/img/emoji/handbag.png differ diff --git a/ui/img/emoji/hankey.png b/ui/img/emoji/hankey.png new file mode 100644 index 0000000..73a4dc8 Binary files /dev/null and b/ui/img/emoji/hankey.png differ diff --git a/ui/img/emoji/hash.png b/ui/img/emoji/hash.png new file mode 100644 index 0000000..6765d7d Binary files /dev/null and b/ui/img/emoji/hash.png differ diff --git a/ui/img/emoji/hatched_chick.png b/ui/img/emoji/hatched_chick.png new file mode 100644 index 0000000..39c25bc Binary files /dev/null and b/ui/img/emoji/hatched_chick.png differ diff --git a/ui/img/emoji/hatching_chick.png b/ui/img/emoji/hatching_chick.png new file mode 100644 index 0000000..005a555 Binary files /dev/null and b/ui/img/emoji/hatching_chick.png differ diff --git a/ui/img/emoji/headphones.png b/ui/img/emoji/headphones.png new file mode 100644 index 0000000..ad83000 Binary files /dev/null and b/ui/img/emoji/headphones.png differ diff --git a/ui/img/emoji/hear_no_evil.png b/ui/img/emoji/hear_no_evil.png new file mode 100644 index 0000000..f97a1f9 Binary files /dev/null and b/ui/img/emoji/hear_no_evil.png differ diff --git a/ui/img/emoji/heart.png b/ui/img/emoji/heart.png new file mode 100644 index 0000000..7d7790c Binary files /dev/null and b/ui/img/emoji/heart.png differ diff --git a/ui/img/emoji/heart_decoration.png b/ui/img/emoji/heart_decoration.png new file mode 100644 index 0000000..b8be44d Binary files /dev/null and b/ui/img/emoji/heart_decoration.png differ diff --git a/ui/img/emoji/heart_eyes.png b/ui/img/emoji/heart_eyes.png new file mode 100644 index 0000000..0e57942 Binary files /dev/null and b/ui/img/emoji/heart_eyes.png differ diff --git a/ui/img/emoji/heart_eyes_cat.png b/ui/img/emoji/heart_eyes_cat.png new file mode 100644 index 0000000..eeba240 Binary files /dev/null and b/ui/img/emoji/heart_eyes_cat.png differ diff --git a/ui/img/emoji/heartbeat.png b/ui/img/emoji/heartbeat.png new file mode 100644 index 0000000..b6628f6 Binary files /dev/null and b/ui/img/emoji/heartbeat.png differ diff --git a/ui/img/emoji/heartpulse.png b/ui/img/emoji/heartpulse.png new file mode 100644 index 0000000..a7491cb Binary files /dev/null and b/ui/img/emoji/heartpulse.png differ diff --git a/ui/img/emoji/hearts.png b/ui/img/emoji/hearts.png new file mode 100644 index 0000000..e894715 Binary files /dev/null and b/ui/img/emoji/hearts.png differ diff --git a/ui/img/emoji/heavy_check_mark.png b/ui/img/emoji/heavy_check_mark.png new file mode 100644 index 0000000..d0f010b Binary files /dev/null and b/ui/img/emoji/heavy_check_mark.png differ diff --git a/ui/img/emoji/heavy_division_sign.png b/ui/img/emoji/heavy_division_sign.png new file mode 100644 index 0000000..e193fd2 Binary files /dev/null and b/ui/img/emoji/heavy_division_sign.png differ diff --git a/ui/img/emoji/heavy_dollar_sign.png b/ui/img/emoji/heavy_dollar_sign.png new file mode 100644 index 0000000..5eddfc5 Binary files /dev/null and b/ui/img/emoji/heavy_dollar_sign.png differ diff --git a/ui/img/emoji/heavy_exclamation_mark.png b/ui/img/emoji/heavy_exclamation_mark.png new file mode 100644 index 0000000..4c560f5 Binary files /dev/null and b/ui/img/emoji/heavy_exclamation_mark.png differ diff --git a/ui/img/emoji/heavy_minus_sign.png b/ui/img/emoji/heavy_minus_sign.png new file mode 100644 index 0000000..4a33f90 Binary files /dev/null and b/ui/img/emoji/heavy_minus_sign.png differ diff --git a/ui/img/emoji/heavy_multiplication_x.png b/ui/img/emoji/heavy_multiplication_x.png new file mode 100644 index 0000000..13d6660 Binary files /dev/null and b/ui/img/emoji/heavy_multiplication_x.png differ diff --git a/ui/img/emoji/heavy_plus_sign.png b/ui/img/emoji/heavy_plus_sign.png new file mode 100644 index 0000000..ade3c3a Binary files /dev/null and b/ui/img/emoji/heavy_plus_sign.png differ diff --git a/ui/img/emoji/helicopter.png b/ui/img/emoji/helicopter.png new file mode 100644 index 0000000..8e82a0d Binary files /dev/null and b/ui/img/emoji/helicopter.png differ diff --git a/ui/img/emoji/herb.png b/ui/img/emoji/herb.png new file mode 100644 index 0000000..de1ff1b Binary files /dev/null and b/ui/img/emoji/herb.png differ diff --git a/ui/img/emoji/hibiscus.png b/ui/img/emoji/hibiscus.png new file mode 100644 index 0000000..9365ae2 Binary files /dev/null and b/ui/img/emoji/hibiscus.png differ diff --git a/ui/img/emoji/high_brightness.png b/ui/img/emoji/high_brightness.png new file mode 100644 index 0000000..ba9de7d Binary files /dev/null and b/ui/img/emoji/high_brightness.png differ diff --git a/ui/img/emoji/high_heel.png b/ui/img/emoji/high_heel.png new file mode 100644 index 0000000..525b6a0 Binary files /dev/null and b/ui/img/emoji/high_heel.png differ diff --git a/ui/img/emoji/hocho.png b/ui/img/emoji/hocho.png new file mode 100644 index 0000000..3f05193 Binary files /dev/null and b/ui/img/emoji/hocho.png differ diff --git a/ui/img/emoji/honey_pot.png b/ui/img/emoji/honey_pot.png new file mode 100644 index 0000000..7327889 Binary files /dev/null and b/ui/img/emoji/honey_pot.png differ diff --git a/ui/img/emoji/honeybee.png b/ui/img/emoji/honeybee.png new file mode 100644 index 0000000..f537339 Binary files /dev/null and b/ui/img/emoji/honeybee.png differ diff --git a/ui/img/emoji/horse.png b/ui/img/emoji/horse.png new file mode 100644 index 0000000..78d580a Binary files /dev/null and b/ui/img/emoji/horse.png differ diff --git a/ui/img/emoji/horse_racing.png b/ui/img/emoji/horse_racing.png new file mode 100644 index 0000000..e3bbaec Binary files /dev/null and b/ui/img/emoji/horse_racing.png differ diff --git a/ui/img/emoji/hospital.png b/ui/img/emoji/hospital.png new file mode 100644 index 0000000..c05c493 Binary files /dev/null and b/ui/img/emoji/hospital.png differ diff --git a/ui/img/emoji/hotel.png b/ui/img/emoji/hotel.png new file mode 100644 index 0000000..d29f276 Binary files /dev/null and b/ui/img/emoji/hotel.png differ diff --git a/ui/img/emoji/hotsprings.png b/ui/img/emoji/hotsprings.png new file mode 100644 index 0000000..a0bc9d7 Binary files /dev/null and b/ui/img/emoji/hotsprings.png differ diff --git a/ui/img/emoji/hourglass.png b/ui/img/emoji/hourglass.png new file mode 100644 index 0000000..405aab4 Binary files /dev/null and b/ui/img/emoji/hourglass.png differ diff --git a/ui/img/emoji/hourglass_flowing_sand.png b/ui/img/emoji/hourglass_flowing_sand.png new file mode 100644 index 0000000..b68eb69 Binary files /dev/null and b/ui/img/emoji/hourglass_flowing_sand.png differ diff --git a/ui/img/emoji/house.png b/ui/img/emoji/house.png new file mode 100644 index 0000000..95b9ee0 Binary files /dev/null and b/ui/img/emoji/house.png differ diff --git a/ui/img/emoji/house_with_garden.png b/ui/img/emoji/house_with_garden.png new file mode 100644 index 0000000..3338fb7 Binary files /dev/null and b/ui/img/emoji/house_with_garden.png differ diff --git a/ui/img/emoji/hurtrealbad.png b/ui/img/emoji/hurtrealbad.png new file mode 100644 index 0000000..146ef1a Binary files /dev/null and b/ui/img/emoji/hurtrealbad.png differ diff --git a/ui/img/emoji/hushed.png b/ui/img/emoji/hushed.png new file mode 100644 index 0000000..bbd2cd4 Binary files /dev/null and b/ui/img/emoji/hushed.png differ diff --git a/ui/img/emoji/ice_cream.png b/ui/img/emoji/ice_cream.png new file mode 100644 index 0000000..190be01 Binary files /dev/null and b/ui/img/emoji/ice_cream.png differ diff --git a/ui/img/emoji/icecream.png b/ui/img/emoji/icecream.png new file mode 100644 index 0000000..871ce09 Binary files /dev/null and b/ui/img/emoji/icecream.png differ diff --git a/ui/img/emoji/id.png b/ui/img/emoji/id.png new file mode 100644 index 0000000..47437a7 Binary files /dev/null and b/ui/img/emoji/id.png differ diff --git a/ui/img/emoji/ideograph_advantage.png b/ui/img/emoji/ideograph_advantage.png new file mode 100644 index 0000000..3c1334d Binary files /dev/null and b/ui/img/emoji/ideograph_advantage.png differ diff --git a/ui/img/emoji/imp.png b/ui/img/emoji/imp.png new file mode 100644 index 0000000..fa7d9dc Binary files /dev/null and b/ui/img/emoji/imp.png differ diff --git a/ui/img/emoji/inbox_tray.png b/ui/img/emoji/inbox_tray.png new file mode 100644 index 0000000..e2df0f8 Binary files /dev/null and b/ui/img/emoji/inbox_tray.png differ diff --git a/ui/img/emoji/incoming_envelope.png b/ui/img/emoji/incoming_envelope.png new file mode 100644 index 0000000..afc8271 Binary files /dev/null and b/ui/img/emoji/incoming_envelope.png differ diff --git a/ui/img/emoji/information_desk_person.png b/ui/img/emoji/information_desk_person.png new file mode 100644 index 0000000..52c0a50 Binary files /dev/null and b/ui/img/emoji/information_desk_person.png differ diff --git a/ui/img/emoji/information_source.png b/ui/img/emoji/information_source.png new file mode 100644 index 0000000..9cb8b09 Binary files /dev/null and b/ui/img/emoji/information_source.png differ diff --git a/ui/img/emoji/innocent.png b/ui/img/emoji/innocent.png new file mode 100644 index 0000000..503b614 Binary files /dev/null and b/ui/img/emoji/innocent.png differ diff --git a/ui/img/emoji/interrobang.png b/ui/img/emoji/interrobang.png new file mode 100644 index 0000000..64304b9 Binary files /dev/null and b/ui/img/emoji/interrobang.png differ diff --git a/ui/img/emoji/iphone.png b/ui/img/emoji/iphone.png new file mode 100644 index 0000000..df00710 Binary files /dev/null and b/ui/img/emoji/iphone.png differ diff --git a/ui/img/emoji/it.png b/ui/img/emoji/it.png new file mode 100644 index 0000000..70bc9f3 Binary files /dev/null and b/ui/img/emoji/it.png differ diff --git a/ui/img/emoji/izakaya_lantern.png b/ui/img/emoji/izakaya_lantern.png new file mode 100644 index 0000000..18730ad Binary files /dev/null and b/ui/img/emoji/izakaya_lantern.png differ diff --git a/ui/img/emoji/jack_o_lantern.png b/ui/img/emoji/jack_o_lantern.png new file mode 100644 index 0000000..1f7667e Binary files /dev/null and b/ui/img/emoji/jack_o_lantern.png differ diff --git a/ui/img/emoji/japan.png b/ui/img/emoji/japan.png new file mode 100644 index 0000000..4593280 Binary files /dev/null and b/ui/img/emoji/japan.png differ diff --git a/ui/img/emoji/japanese_castle.png b/ui/img/emoji/japanese_castle.png new file mode 100644 index 0000000..f225ab2 Binary files /dev/null and b/ui/img/emoji/japanese_castle.png differ diff --git a/ui/img/emoji/japanese_goblin.png b/ui/img/emoji/japanese_goblin.png new file mode 100644 index 0000000..bd21b18 Binary files /dev/null and b/ui/img/emoji/japanese_goblin.png differ diff --git a/ui/img/emoji/japanese_ogre.png b/ui/img/emoji/japanese_ogre.png new file mode 100644 index 0000000..e9f5471 Binary files /dev/null and b/ui/img/emoji/japanese_ogre.png differ diff --git a/ui/img/emoji/jeans.png b/ui/img/emoji/jeans.png new file mode 100644 index 0000000..d721cea Binary files /dev/null and b/ui/img/emoji/jeans.png differ diff --git a/ui/img/emoji/joy.png b/ui/img/emoji/joy.png new file mode 100644 index 0000000..47df693 Binary files /dev/null and b/ui/img/emoji/joy.png differ diff --git a/ui/img/emoji/joy_cat.png b/ui/img/emoji/joy_cat.png new file mode 100644 index 0000000..6c60cb0 Binary files /dev/null and b/ui/img/emoji/joy_cat.png differ diff --git a/ui/img/emoji/jp.png b/ui/img/emoji/jp.png new file mode 100644 index 0000000..b786efb Binary files /dev/null and b/ui/img/emoji/jp.png differ diff --git a/ui/img/emoji/key.png b/ui/img/emoji/key.png new file mode 100644 index 0000000..3467321 Binary files /dev/null and b/ui/img/emoji/key.png differ diff --git a/ui/img/emoji/keycap_ten.png b/ui/img/emoji/keycap_ten.png new file mode 100644 index 0000000..71dac1c Binary files /dev/null and b/ui/img/emoji/keycap_ten.png differ diff --git a/ui/img/emoji/kimono.png b/ui/img/emoji/kimono.png new file mode 100644 index 0000000..34ffe13 Binary files /dev/null and b/ui/img/emoji/kimono.png differ diff --git a/ui/img/emoji/kiss.png b/ui/img/emoji/kiss.png new file mode 100644 index 0000000..14fd991 Binary files /dev/null and b/ui/img/emoji/kiss.png differ diff --git a/ui/img/emoji/kissing.png b/ui/img/emoji/kissing.png new file mode 100644 index 0000000..f3c8dcd Binary files /dev/null and b/ui/img/emoji/kissing.png differ diff --git a/ui/img/emoji/kissing_cat.png b/ui/img/emoji/kissing_cat.png new file mode 100644 index 0000000..adc62fb Binary files /dev/null and b/ui/img/emoji/kissing_cat.png differ diff --git a/ui/img/emoji/kissing_closed_eyes.png b/ui/img/emoji/kissing_closed_eyes.png new file mode 100644 index 0000000..449de19 Binary files /dev/null and b/ui/img/emoji/kissing_closed_eyes.png differ diff --git a/ui/img/emoji/kissing_face.png b/ui/img/emoji/kissing_face.png new file mode 100644 index 0000000..449de19 Binary files /dev/null and b/ui/img/emoji/kissing_face.png differ diff --git a/ui/img/emoji/kissing_heart.png b/ui/img/emoji/kissing_heart.png new file mode 100644 index 0000000..af9a80b Binary files /dev/null and b/ui/img/emoji/kissing_heart.png differ diff --git a/ui/img/emoji/kissing_smiling_eyes.png b/ui/img/emoji/kissing_smiling_eyes.png new file mode 100644 index 0000000..57f7b49 Binary files /dev/null and b/ui/img/emoji/kissing_smiling_eyes.png differ diff --git a/ui/img/emoji/koala.png b/ui/img/emoji/koala.png new file mode 100644 index 0000000..e17bd3c Binary files /dev/null and b/ui/img/emoji/koala.png differ diff --git a/ui/img/emoji/koko.png b/ui/img/emoji/koko.png new file mode 100644 index 0000000..3bef28c Binary files /dev/null and b/ui/img/emoji/koko.png differ diff --git a/ui/img/emoji/kr.png b/ui/img/emoji/kr.png new file mode 100644 index 0000000..b4c0c1b Binary files /dev/null and b/ui/img/emoji/kr.png differ diff --git a/ui/img/emoji/large_blue_circle.png b/ui/img/emoji/large_blue_circle.png new file mode 100644 index 0000000..a5b4ad4 Binary files /dev/null and b/ui/img/emoji/large_blue_circle.png differ diff --git a/ui/img/emoji/large_blue_diamond.png b/ui/img/emoji/large_blue_diamond.png new file mode 100644 index 0000000..f4598ec Binary files /dev/null and b/ui/img/emoji/large_blue_diamond.png differ diff --git a/ui/img/emoji/large_orange_diamond.png b/ui/img/emoji/large_orange_diamond.png new file mode 100644 index 0000000..803725a Binary files /dev/null and b/ui/img/emoji/large_orange_diamond.png differ diff --git a/ui/img/emoji/last_quarter_moon.png b/ui/img/emoji/last_quarter_moon.png new file mode 100644 index 0000000..6ae30d6 Binary files /dev/null and b/ui/img/emoji/last_quarter_moon.png differ diff --git a/ui/img/emoji/last_quarter_moon_with_face.png b/ui/img/emoji/last_quarter_moon_with_face.png new file mode 100644 index 0000000..9ece82d Binary files /dev/null and b/ui/img/emoji/last_quarter_moon_with_face.png differ diff --git a/ui/img/emoji/laughing.png b/ui/img/emoji/laughing.png new file mode 100644 index 0000000..11c91eb Binary files /dev/null and b/ui/img/emoji/laughing.png differ diff --git a/ui/img/emoji/leaves.png b/ui/img/emoji/leaves.png new file mode 100644 index 0000000..5229e06 Binary files /dev/null and b/ui/img/emoji/leaves.png differ diff --git a/ui/img/emoji/ledger.png b/ui/img/emoji/ledger.png new file mode 100644 index 0000000..e4f72ac Binary files /dev/null and b/ui/img/emoji/ledger.png differ diff --git a/ui/img/emoji/left_luggage.png b/ui/img/emoji/left_luggage.png new file mode 100644 index 0000000..1c08b46 Binary files /dev/null and b/ui/img/emoji/left_luggage.png differ diff --git a/ui/img/emoji/left_right_arrow.png b/ui/img/emoji/left_right_arrow.png new file mode 100644 index 0000000..b9fd11c Binary files /dev/null and b/ui/img/emoji/left_right_arrow.png differ diff --git a/ui/img/emoji/leftwards_arrow_with_hook.png b/ui/img/emoji/leftwards_arrow_with_hook.png new file mode 100644 index 0000000..bc45dfe Binary files /dev/null and b/ui/img/emoji/leftwards_arrow_with_hook.png differ diff --git a/ui/img/emoji/lemon.png b/ui/img/emoji/lemon.png new file mode 100644 index 0000000..9814dc9 Binary files /dev/null and b/ui/img/emoji/lemon.png differ diff --git a/ui/img/emoji/leo.png b/ui/img/emoji/leo.png new file mode 100644 index 0000000..e025933 Binary files /dev/null and b/ui/img/emoji/leo.png differ diff --git a/ui/img/emoji/leopard.png b/ui/img/emoji/leopard.png new file mode 100644 index 0000000..3e738d2 Binary files /dev/null and b/ui/img/emoji/leopard.png differ diff --git a/ui/img/emoji/libra.png b/ui/img/emoji/libra.png new file mode 100644 index 0000000..6f4a927 Binary files /dev/null and b/ui/img/emoji/libra.png differ diff --git a/ui/img/emoji/light_rail.png b/ui/img/emoji/light_rail.png new file mode 100644 index 0000000..bcfe801 Binary files /dev/null and b/ui/img/emoji/light_rail.png differ diff --git a/ui/img/emoji/link.png b/ui/img/emoji/link.png new file mode 100644 index 0000000..0239e48 Binary files /dev/null and b/ui/img/emoji/link.png differ diff --git a/ui/img/emoji/lips.png b/ui/img/emoji/lips.png new file mode 100644 index 0000000..826ed11 Binary files /dev/null and b/ui/img/emoji/lips.png differ diff --git a/ui/img/emoji/lipstick.png b/ui/img/emoji/lipstick.png new file mode 100644 index 0000000..82f990c Binary files /dev/null and b/ui/img/emoji/lipstick.png differ diff --git a/ui/img/emoji/lock.png b/ui/img/emoji/lock.png new file mode 100644 index 0000000..4892b02 Binary files /dev/null and b/ui/img/emoji/lock.png differ diff --git a/ui/img/emoji/lock_with_ink_pen.png b/ui/img/emoji/lock_with_ink_pen.png new file mode 100644 index 0000000..375e67e Binary files /dev/null and b/ui/img/emoji/lock_with_ink_pen.png differ diff --git a/ui/img/emoji/lollipop.png b/ui/img/emoji/lollipop.png new file mode 100644 index 0000000..ba55e70 Binary files /dev/null and b/ui/img/emoji/lollipop.png differ diff --git a/ui/img/emoji/loop.png b/ui/img/emoji/loop.png new file mode 100644 index 0000000..ef34df3 Binary files /dev/null and b/ui/img/emoji/loop.png differ diff --git a/ui/img/emoji/loudspeaker.png b/ui/img/emoji/loudspeaker.png new file mode 100644 index 0000000..752385e Binary files /dev/null and b/ui/img/emoji/loudspeaker.png differ diff --git a/ui/img/emoji/love_hotel.png b/ui/img/emoji/love_hotel.png new file mode 100644 index 0000000..44d7db8 Binary files /dev/null and b/ui/img/emoji/love_hotel.png differ diff --git a/ui/img/emoji/love_letter.png b/ui/img/emoji/love_letter.png new file mode 100644 index 0000000..e29981f Binary files /dev/null and b/ui/img/emoji/love_letter.png differ diff --git a/ui/img/emoji/low_brightness.png b/ui/img/emoji/low_brightness.png new file mode 100644 index 0000000..ea15bde Binary files /dev/null and b/ui/img/emoji/low_brightness.png differ diff --git a/ui/img/emoji/m.png b/ui/img/emoji/m.png new file mode 100644 index 0000000..7e3a3bf Binary files /dev/null and b/ui/img/emoji/m.png differ diff --git a/ui/img/emoji/mag.png b/ui/img/emoji/mag.png new file mode 100644 index 0000000..aa5b1d7 Binary files /dev/null and b/ui/img/emoji/mag.png differ diff --git a/ui/img/emoji/mag_right.png b/ui/img/emoji/mag_right.png new file mode 100644 index 0000000..6e6cf11 Binary files /dev/null and b/ui/img/emoji/mag_right.png differ diff --git a/ui/img/emoji/mahjong.png b/ui/img/emoji/mahjong.png new file mode 100644 index 0000000..f51ce65 Binary files /dev/null and b/ui/img/emoji/mahjong.png differ diff --git a/ui/img/emoji/mailbox.png b/ui/img/emoji/mailbox.png new file mode 100644 index 0000000..8351e70 Binary files /dev/null and b/ui/img/emoji/mailbox.png differ diff --git a/ui/img/emoji/mailbox_closed.png b/ui/img/emoji/mailbox_closed.png new file mode 100644 index 0000000..a5982b6 Binary files /dev/null and b/ui/img/emoji/mailbox_closed.png differ diff --git a/ui/img/emoji/mailbox_with_mail.png b/ui/img/emoji/mailbox_with_mail.png new file mode 100644 index 0000000..dae3459 Binary files /dev/null and b/ui/img/emoji/mailbox_with_mail.png differ diff --git a/ui/img/emoji/mailbox_with_no_mail.png b/ui/img/emoji/mailbox_with_no_mail.png new file mode 100644 index 0000000..59f15c5 Binary files /dev/null and b/ui/img/emoji/mailbox_with_no_mail.png differ diff --git a/ui/img/emoji/man.png b/ui/img/emoji/man.png new file mode 100644 index 0000000..d9bfa26 Binary files /dev/null and b/ui/img/emoji/man.png differ diff --git a/ui/img/emoji/man_with_gua_pi_mao.png b/ui/img/emoji/man_with_gua_pi_mao.png new file mode 100644 index 0000000..7aad74b Binary files /dev/null and b/ui/img/emoji/man_with_gua_pi_mao.png differ diff --git a/ui/img/emoji/man_with_turban.png b/ui/img/emoji/man_with_turban.png new file mode 100644 index 0000000..036604c Binary files /dev/null and b/ui/img/emoji/man_with_turban.png differ diff --git a/ui/img/emoji/mans_shoe.png b/ui/img/emoji/mans_shoe.png new file mode 100644 index 0000000..ecba9ba Binary files /dev/null and b/ui/img/emoji/mans_shoe.png differ diff --git a/ui/img/emoji/maple_leaf.png b/ui/img/emoji/maple_leaf.png new file mode 100644 index 0000000..4e9b472 Binary files /dev/null and b/ui/img/emoji/maple_leaf.png differ diff --git a/ui/img/emoji/mask.png b/ui/img/emoji/mask.png new file mode 100644 index 0000000..05887e9 Binary files /dev/null and b/ui/img/emoji/mask.png differ diff --git a/ui/img/emoji/massage.png b/ui/img/emoji/massage.png new file mode 100644 index 0000000..dd30d15 Binary files /dev/null and b/ui/img/emoji/massage.png differ diff --git a/ui/img/emoji/meat_on_bone.png b/ui/img/emoji/meat_on_bone.png new file mode 100644 index 0000000..5b79a66 Binary files /dev/null and b/ui/img/emoji/meat_on_bone.png differ diff --git a/ui/img/emoji/mega.png b/ui/img/emoji/mega.png new file mode 100644 index 0000000..022df2f Binary files /dev/null and b/ui/img/emoji/mega.png differ diff --git a/ui/img/emoji/melon.png b/ui/img/emoji/melon.png new file mode 100644 index 0000000..11c13cb Binary files /dev/null and b/ui/img/emoji/melon.png differ diff --git a/ui/img/emoji/memo.png b/ui/img/emoji/memo.png new file mode 100644 index 0000000..fc97ddb Binary files /dev/null and b/ui/img/emoji/memo.png differ diff --git a/ui/img/emoji/mens.png b/ui/img/emoji/mens.png new file mode 100644 index 0000000..abccfc9 Binary files /dev/null and b/ui/img/emoji/mens.png differ diff --git a/ui/img/emoji/metal.png b/ui/img/emoji/metal.png new file mode 100644 index 0000000..94f1fda Binary files /dev/null and b/ui/img/emoji/metal.png differ diff --git a/ui/img/emoji/metro.png b/ui/img/emoji/metro.png new file mode 100644 index 0000000..4acf5ab Binary files /dev/null and b/ui/img/emoji/metro.png differ diff --git a/ui/img/emoji/microphone.png b/ui/img/emoji/microphone.png new file mode 100644 index 0000000..68c74ad Binary files /dev/null and b/ui/img/emoji/microphone.png differ diff --git a/ui/img/emoji/microscope.png b/ui/img/emoji/microscope.png new file mode 100644 index 0000000..8b7a5e4 Binary files /dev/null and b/ui/img/emoji/microscope.png differ diff --git a/ui/img/emoji/milky_way.png b/ui/img/emoji/milky_way.png new file mode 100644 index 0000000..901090a Binary files /dev/null and b/ui/img/emoji/milky_way.png differ diff --git a/ui/img/emoji/minibus.png b/ui/img/emoji/minibus.png new file mode 100644 index 0000000..c52cef2 Binary files /dev/null and b/ui/img/emoji/minibus.png differ diff --git a/ui/img/emoji/minidisc.png b/ui/img/emoji/minidisc.png new file mode 100644 index 0000000..e19cc5d Binary files /dev/null and b/ui/img/emoji/minidisc.png differ diff --git a/ui/img/emoji/mobile_phone_off.png b/ui/img/emoji/mobile_phone_off.png new file mode 100644 index 0000000..fa16c76 Binary files /dev/null and b/ui/img/emoji/mobile_phone_off.png differ diff --git a/ui/img/emoji/money_with_wings.png b/ui/img/emoji/money_with_wings.png new file mode 100644 index 0000000..581a824 Binary files /dev/null and b/ui/img/emoji/money_with_wings.png differ diff --git a/ui/img/emoji/moneybag.png b/ui/img/emoji/moneybag.png new file mode 100644 index 0000000..5546c04 Binary files /dev/null and b/ui/img/emoji/moneybag.png differ diff --git a/ui/img/emoji/monkey.png b/ui/img/emoji/monkey.png new file mode 100644 index 0000000..6407035 Binary files /dev/null and b/ui/img/emoji/monkey.png differ diff --git a/ui/img/emoji/monkey_face.png b/ui/img/emoji/monkey_face.png new file mode 100644 index 0000000..6964cf4 Binary files /dev/null and b/ui/img/emoji/monkey_face.png differ diff --git a/ui/img/emoji/monorail.png b/ui/img/emoji/monorail.png new file mode 100644 index 0000000..913d300 Binary files /dev/null and b/ui/img/emoji/monorail.png differ diff --git a/ui/img/emoji/moon.png b/ui/img/emoji/moon.png new file mode 100644 index 0000000..afdb450 Binary files /dev/null and b/ui/img/emoji/moon.png differ diff --git a/ui/img/emoji/mortar_board.png b/ui/img/emoji/mortar_board.png new file mode 100644 index 0000000..84513f6 Binary files /dev/null and b/ui/img/emoji/mortar_board.png differ diff --git a/ui/img/emoji/mount_fuji.png b/ui/img/emoji/mount_fuji.png new file mode 100644 index 0000000..4c313e5 Binary files /dev/null and b/ui/img/emoji/mount_fuji.png differ diff --git a/ui/img/emoji/mountain_bicyclist.png b/ui/img/emoji/mountain_bicyclist.png new file mode 100644 index 0000000..b698897 Binary files /dev/null and b/ui/img/emoji/mountain_bicyclist.png differ diff --git a/ui/img/emoji/mountain_cableway.png b/ui/img/emoji/mountain_cableway.png new file mode 100644 index 0000000..5688bb2 Binary files /dev/null and b/ui/img/emoji/mountain_cableway.png differ diff --git a/ui/img/emoji/mountain_railway.png b/ui/img/emoji/mountain_railway.png new file mode 100644 index 0000000..1f3d1aa Binary files /dev/null and b/ui/img/emoji/mountain_railway.png differ diff --git a/ui/img/emoji/mouse.png b/ui/img/emoji/mouse.png new file mode 100644 index 0000000..8ff162e Binary files /dev/null and b/ui/img/emoji/mouse.png differ diff --git a/ui/img/emoji/mouse2.png b/ui/img/emoji/mouse2.png new file mode 100644 index 0000000..2d777e5 Binary files /dev/null and b/ui/img/emoji/mouse2.png differ diff --git a/ui/img/emoji/movie_camera.png b/ui/img/emoji/movie_camera.png new file mode 100644 index 0000000..9c14384 Binary files /dev/null and b/ui/img/emoji/movie_camera.png differ diff --git a/ui/img/emoji/moyai.png b/ui/img/emoji/moyai.png new file mode 100644 index 0000000..61a1a9c Binary files /dev/null and b/ui/img/emoji/moyai.png differ diff --git a/ui/img/emoji/muscle.png b/ui/img/emoji/muscle.png new file mode 100644 index 0000000..19f92ef Binary files /dev/null and b/ui/img/emoji/muscle.png differ diff --git a/ui/img/emoji/mushroom.png b/ui/img/emoji/mushroom.png new file mode 100644 index 0000000..5eeed8e Binary files /dev/null and b/ui/img/emoji/mushroom.png differ diff --git a/ui/img/emoji/musical_keyboard.png b/ui/img/emoji/musical_keyboard.png new file mode 100644 index 0000000..93647a4 Binary files /dev/null and b/ui/img/emoji/musical_keyboard.png differ diff --git a/ui/img/emoji/musical_note.png b/ui/img/emoji/musical_note.png new file mode 100644 index 0000000..68b261b Binary files /dev/null and b/ui/img/emoji/musical_note.png differ diff --git a/ui/img/emoji/musical_score.png b/ui/img/emoji/musical_score.png new file mode 100644 index 0000000..c99e338 Binary files /dev/null and b/ui/img/emoji/musical_score.png differ diff --git a/ui/img/emoji/mute.png b/ui/img/emoji/mute.png new file mode 100644 index 0000000..4cf67c3 Binary files /dev/null and b/ui/img/emoji/mute.png differ diff --git a/ui/img/emoji/nail_care.png b/ui/img/emoji/nail_care.png new file mode 100644 index 0000000..6a66e63 Binary files /dev/null and b/ui/img/emoji/nail_care.png differ diff --git a/ui/img/emoji/name_badge.png b/ui/img/emoji/name_badge.png new file mode 100644 index 0000000..2b712dc Binary files /dev/null and b/ui/img/emoji/name_badge.png differ diff --git a/ui/img/emoji/neckbeard.png b/ui/img/emoji/neckbeard.png new file mode 100644 index 0000000..6e31d16 Binary files /dev/null and b/ui/img/emoji/neckbeard.png differ diff --git a/ui/img/emoji/necktie.png b/ui/img/emoji/necktie.png new file mode 100644 index 0000000..80461c6 Binary files /dev/null and b/ui/img/emoji/necktie.png differ diff --git a/ui/img/emoji/negative_squared_cross_mark.png b/ui/img/emoji/negative_squared_cross_mark.png new file mode 100644 index 0000000..b47a0ce Binary files /dev/null and b/ui/img/emoji/negative_squared_cross_mark.png differ diff --git a/ui/img/emoji/neutral_face.png b/ui/img/emoji/neutral_face.png new file mode 100644 index 0000000..682a1ba Binary files /dev/null and b/ui/img/emoji/neutral_face.png differ diff --git a/ui/img/emoji/new.png b/ui/img/emoji/new.png new file mode 100644 index 0000000..28d1570 Binary files /dev/null and b/ui/img/emoji/new.png differ diff --git a/ui/img/emoji/new_moon.png b/ui/img/emoji/new_moon.png new file mode 100644 index 0000000..72492cb Binary files /dev/null and b/ui/img/emoji/new_moon.png differ diff --git a/ui/img/emoji/new_moon_with_face.png b/ui/img/emoji/new_moon_with_face.png new file mode 100644 index 0000000..21a696e Binary files /dev/null and b/ui/img/emoji/new_moon_with_face.png differ diff --git a/ui/img/emoji/newspaper.png b/ui/img/emoji/newspaper.png new file mode 100644 index 0000000..60c3394 Binary files /dev/null and b/ui/img/emoji/newspaper.png differ diff --git a/ui/img/emoji/ng.png b/ui/img/emoji/ng.png new file mode 100644 index 0000000..2ca180a Binary files /dev/null and b/ui/img/emoji/ng.png differ diff --git a/ui/img/emoji/nine.png b/ui/img/emoji/nine.png new file mode 100644 index 0000000..8006cc9 Binary files /dev/null and b/ui/img/emoji/nine.png differ diff --git a/ui/img/emoji/no_bell.png b/ui/img/emoji/no_bell.png new file mode 100644 index 0000000..613b81c Binary files /dev/null and b/ui/img/emoji/no_bell.png differ diff --git a/ui/img/emoji/no_bicycles.png b/ui/img/emoji/no_bicycles.png new file mode 100644 index 0000000..4b26216 Binary files /dev/null and b/ui/img/emoji/no_bicycles.png differ diff --git a/ui/img/emoji/no_entry.png b/ui/img/emoji/no_entry.png new file mode 100644 index 0000000..cf2086a Binary files /dev/null and b/ui/img/emoji/no_entry.png differ diff --git a/ui/img/emoji/no_entry_sign.png b/ui/img/emoji/no_entry_sign.png new file mode 100644 index 0000000..b3231f6 Binary files /dev/null and b/ui/img/emoji/no_entry_sign.png differ diff --git a/ui/img/emoji/no_good.png b/ui/img/emoji/no_good.png new file mode 100644 index 0000000..d459a35 Binary files /dev/null and b/ui/img/emoji/no_good.png differ diff --git a/ui/img/emoji/no_mobile_phones.png b/ui/img/emoji/no_mobile_phones.png new file mode 100644 index 0000000..41df57c Binary files /dev/null and b/ui/img/emoji/no_mobile_phones.png differ diff --git a/ui/img/emoji/no_mouth.png b/ui/img/emoji/no_mouth.png new file mode 100644 index 0000000..e678020 Binary files /dev/null and b/ui/img/emoji/no_mouth.png differ diff --git a/ui/img/emoji/no_pedestrians.png b/ui/img/emoji/no_pedestrians.png new file mode 100644 index 0000000..53ee0f9 Binary files /dev/null and b/ui/img/emoji/no_pedestrians.png differ diff --git a/ui/img/emoji/no_smoking.png b/ui/img/emoji/no_smoking.png new file mode 100644 index 0000000..5880ddf Binary files /dev/null and b/ui/img/emoji/no_smoking.png differ diff --git a/ui/img/emoji/non-potable_water.png b/ui/img/emoji/non-potable_water.png new file mode 100644 index 0000000..1b29d35 Binary files /dev/null and b/ui/img/emoji/non-potable_water.png differ diff --git a/ui/img/emoji/nose.png b/ui/img/emoji/nose.png new file mode 100644 index 0000000..ad17c16 Binary files /dev/null and b/ui/img/emoji/nose.png differ diff --git a/ui/img/emoji/notebook.png b/ui/img/emoji/notebook.png new file mode 100644 index 0000000..5f0a5f6 Binary files /dev/null and b/ui/img/emoji/notebook.png differ diff --git a/ui/img/emoji/notebook_with_decorative_cover.png b/ui/img/emoji/notebook_with_decorative_cover.png new file mode 100644 index 0000000..4f3b14c Binary files /dev/null and b/ui/img/emoji/notebook_with_decorative_cover.png differ diff --git a/ui/img/emoji/notes.png b/ui/img/emoji/notes.png new file mode 100644 index 0000000..0956d6a Binary files /dev/null and b/ui/img/emoji/notes.png differ diff --git a/ui/img/emoji/nut_and_bolt.png b/ui/img/emoji/nut_and_bolt.png new file mode 100644 index 0000000..bddfa72 Binary files /dev/null and b/ui/img/emoji/nut_and_bolt.png differ diff --git a/ui/img/emoji/o.png b/ui/img/emoji/o.png new file mode 100644 index 0000000..1ff846c Binary files /dev/null and b/ui/img/emoji/o.png differ diff --git a/ui/img/emoji/o2.png b/ui/img/emoji/o2.png new file mode 100644 index 0000000..d85f9fb Binary files /dev/null and b/ui/img/emoji/o2.png differ diff --git a/ui/img/emoji/ocean.png b/ui/img/emoji/ocean.png new file mode 100644 index 0000000..f8d520c Binary files /dev/null and b/ui/img/emoji/ocean.png differ diff --git a/ui/img/emoji/octocat.png b/ui/img/emoji/octocat.png new file mode 100644 index 0000000..d296f25 Binary files /dev/null and b/ui/img/emoji/octocat.png differ diff --git a/ui/img/emoji/octopus.png b/ui/img/emoji/octopus.png new file mode 100644 index 0000000..52ce64b Binary files /dev/null and b/ui/img/emoji/octopus.png differ diff --git a/ui/img/emoji/oden.png b/ui/img/emoji/oden.png new file mode 100644 index 0000000..73add1c Binary files /dev/null and b/ui/img/emoji/oden.png differ diff --git a/ui/img/emoji/office.png b/ui/img/emoji/office.png new file mode 100644 index 0000000..53c3ef8 Binary files /dev/null and b/ui/img/emoji/office.png differ diff --git a/ui/img/emoji/ok.png b/ui/img/emoji/ok.png new file mode 100644 index 0000000..6433d1a Binary files /dev/null and b/ui/img/emoji/ok.png differ diff --git a/ui/img/emoji/ok_hand.png b/ui/img/emoji/ok_hand.png new file mode 100644 index 0000000..80c5aeb Binary files /dev/null and b/ui/img/emoji/ok_hand.png differ diff --git a/ui/img/emoji/ok_woman.png b/ui/img/emoji/ok_woman.png new file mode 100644 index 0000000..e8b9819 Binary files /dev/null and b/ui/img/emoji/ok_woman.png differ diff --git a/ui/img/emoji/older_man.png b/ui/img/emoji/older_man.png new file mode 100644 index 0000000..149f0cf Binary files /dev/null and b/ui/img/emoji/older_man.png differ diff --git a/ui/img/emoji/older_woman.png b/ui/img/emoji/older_woman.png new file mode 100644 index 0000000..f839565 Binary files /dev/null and b/ui/img/emoji/older_woman.png differ diff --git a/ui/img/emoji/on.png b/ui/img/emoji/on.png new file mode 100644 index 0000000..4cd69a1 Binary files /dev/null and b/ui/img/emoji/on.png differ diff --git a/ui/img/emoji/oncoming_automobile.png b/ui/img/emoji/oncoming_automobile.png new file mode 100644 index 0000000..cb46de2 Binary files /dev/null and b/ui/img/emoji/oncoming_automobile.png differ diff --git a/ui/img/emoji/oncoming_bus.png b/ui/img/emoji/oncoming_bus.png new file mode 100644 index 0000000..3695f76 Binary files /dev/null and b/ui/img/emoji/oncoming_bus.png differ diff --git a/ui/img/emoji/oncoming_police_car.png b/ui/img/emoji/oncoming_police_car.png new file mode 100644 index 0000000..af20e7e Binary files /dev/null and b/ui/img/emoji/oncoming_police_car.png differ diff --git a/ui/img/emoji/oncoming_taxi.png b/ui/img/emoji/oncoming_taxi.png new file mode 100644 index 0000000..f78cf31 Binary files /dev/null and b/ui/img/emoji/oncoming_taxi.png differ diff --git a/ui/img/emoji/one.png b/ui/img/emoji/one.png new file mode 100644 index 0000000..2d1f9f8 Binary files /dev/null and b/ui/img/emoji/one.png differ diff --git a/ui/img/emoji/open_file_folder.png b/ui/img/emoji/open_file_folder.png new file mode 100644 index 0000000..2bbbbf5 Binary files /dev/null and b/ui/img/emoji/open_file_folder.png differ diff --git a/ui/img/emoji/open_hands.png b/ui/img/emoji/open_hands.png new file mode 100644 index 0000000..cef9f42 Binary files /dev/null and b/ui/img/emoji/open_hands.png differ diff --git a/ui/img/emoji/open_mouth.png b/ui/img/emoji/open_mouth.png new file mode 100644 index 0000000..daf9142 Binary files /dev/null and b/ui/img/emoji/open_mouth.png differ diff --git a/ui/img/emoji/ophiuchus.png b/ui/img/emoji/ophiuchus.png new file mode 100644 index 0000000..4eef715 Binary files /dev/null and b/ui/img/emoji/ophiuchus.png differ diff --git a/ui/img/emoji/orange_book.png b/ui/img/emoji/orange_book.png new file mode 100644 index 0000000..49650d5 Binary files /dev/null and b/ui/img/emoji/orange_book.png differ diff --git a/ui/img/emoji/outbox_tray.png b/ui/img/emoji/outbox_tray.png new file mode 100644 index 0000000..7ad15e6 Binary files /dev/null and b/ui/img/emoji/outbox_tray.png differ diff --git a/ui/img/emoji/ox.png b/ui/img/emoji/ox.png new file mode 100644 index 0000000..8d98194 Binary files /dev/null and b/ui/img/emoji/ox.png differ diff --git a/ui/img/emoji/page_facing_up.png b/ui/img/emoji/page_facing_up.png new file mode 100644 index 0000000..804c0d7 Binary files /dev/null and b/ui/img/emoji/page_facing_up.png differ diff --git a/ui/img/emoji/page_with_curl.png b/ui/img/emoji/page_with_curl.png new file mode 100644 index 0000000..37cb4de Binary files /dev/null and b/ui/img/emoji/page_with_curl.png differ diff --git a/ui/img/emoji/pager.png b/ui/img/emoji/pager.png new file mode 100644 index 0000000..e3e1fc4 Binary files /dev/null and b/ui/img/emoji/pager.png differ diff --git a/ui/img/emoji/palm_tree.png b/ui/img/emoji/palm_tree.png new file mode 100644 index 0000000..d13b7c6 Binary files /dev/null and b/ui/img/emoji/palm_tree.png differ diff --git a/ui/img/emoji/panda_face.png b/ui/img/emoji/panda_face.png new file mode 100644 index 0000000..a794fb1 Binary files /dev/null and b/ui/img/emoji/panda_face.png differ diff --git a/ui/img/emoji/paperclip.png b/ui/img/emoji/paperclip.png new file mode 100644 index 0000000..677669a Binary files /dev/null and b/ui/img/emoji/paperclip.png differ diff --git a/ui/img/emoji/parking.png b/ui/img/emoji/parking.png new file mode 100644 index 0000000..c24af81 Binary files /dev/null and b/ui/img/emoji/parking.png differ diff --git a/ui/img/emoji/part_alternation_mark.png b/ui/img/emoji/part_alternation_mark.png new file mode 100644 index 0000000..1e5855f Binary files /dev/null and b/ui/img/emoji/part_alternation_mark.png differ diff --git a/ui/img/emoji/partly_sunny.png b/ui/img/emoji/partly_sunny.png new file mode 100644 index 0000000..b3f5bcf Binary files /dev/null and b/ui/img/emoji/partly_sunny.png differ diff --git a/ui/img/emoji/passport_control.png b/ui/img/emoji/passport_control.png new file mode 100644 index 0000000..675b76d Binary files /dev/null and b/ui/img/emoji/passport_control.png differ diff --git a/ui/img/emoji/paw_prints.png b/ui/img/emoji/paw_prints.png new file mode 100644 index 0000000..89b9fec Binary files /dev/null and b/ui/img/emoji/paw_prints.png differ diff --git a/ui/img/emoji/peach.png b/ui/img/emoji/peach.png new file mode 100644 index 0000000..ee2139e Binary files /dev/null and b/ui/img/emoji/peach.png differ diff --git a/ui/img/emoji/pear.png b/ui/img/emoji/pear.png new file mode 100644 index 0000000..f24aca8 Binary files /dev/null and b/ui/img/emoji/pear.png differ diff --git a/ui/img/emoji/pencil.png b/ui/img/emoji/pencil.png new file mode 100644 index 0000000..fc97ddb Binary files /dev/null and b/ui/img/emoji/pencil.png differ diff --git a/ui/img/emoji/pencil2.png b/ui/img/emoji/pencil2.png new file mode 100644 index 0000000..64c2d9b Binary files /dev/null and b/ui/img/emoji/pencil2.png differ diff --git a/ui/img/emoji/penguin.png b/ui/img/emoji/penguin.png new file mode 100644 index 0000000..d8edbcb Binary files /dev/null and b/ui/img/emoji/penguin.png differ diff --git a/ui/img/emoji/pensive.png b/ui/img/emoji/pensive.png new file mode 100644 index 0000000..4159f3c Binary files /dev/null and b/ui/img/emoji/pensive.png differ diff --git a/ui/img/emoji/performing_arts.png b/ui/img/emoji/performing_arts.png new file mode 100644 index 0000000..899fbe5 Binary files /dev/null and b/ui/img/emoji/performing_arts.png differ diff --git a/ui/img/emoji/persevere.png b/ui/img/emoji/persevere.png new file mode 100644 index 0000000..f99f6da Binary files /dev/null and b/ui/img/emoji/persevere.png differ diff --git a/ui/img/emoji/person_frowning.png b/ui/img/emoji/person_frowning.png new file mode 100644 index 0000000..6f34d5e Binary files /dev/null and b/ui/img/emoji/person_frowning.png differ diff --git a/ui/img/emoji/person_with_blond_hair.png b/ui/img/emoji/person_with_blond_hair.png new file mode 100644 index 0000000..c144301 Binary files /dev/null and b/ui/img/emoji/person_with_blond_hair.png differ diff --git a/ui/img/emoji/person_with_pouting_face.png b/ui/img/emoji/person_with_pouting_face.png new file mode 100644 index 0000000..c4a95c3 Binary files /dev/null and b/ui/img/emoji/person_with_pouting_face.png differ diff --git a/ui/img/emoji/phone.png b/ui/img/emoji/phone.png new file mode 100644 index 0000000..87d2559 Binary files /dev/null and b/ui/img/emoji/phone.png differ diff --git a/ui/img/emoji/pig.png b/ui/img/emoji/pig.png new file mode 100644 index 0000000..f7f273c Binary files /dev/null and b/ui/img/emoji/pig.png differ diff --git a/ui/img/emoji/pig2.png b/ui/img/emoji/pig2.png new file mode 100644 index 0000000..fec3374 Binary files /dev/null and b/ui/img/emoji/pig2.png differ diff --git a/ui/img/emoji/pig_nose.png b/ui/img/emoji/pig_nose.png new file mode 100644 index 0000000..38d6124 Binary files /dev/null and b/ui/img/emoji/pig_nose.png differ diff --git a/ui/img/emoji/pill.png b/ui/img/emoji/pill.png new file mode 100644 index 0000000..cd84a78 Binary files /dev/null and b/ui/img/emoji/pill.png differ diff --git a/ui/img/emoji/pineapple.png b/ui/img/emoji/pineapple.png new file mode 100644 index 0000000..d6f8e28 Binary files /dev/null and b/ui/img/emoji/pineapple.png differ diff --git a/ui/img/emoji/pisces.png b/ui/img/emoji/pisces.png new file mode 100644 index 0000000..6db2c3d Binary files /dev/null and b/ui/img/emoji/pisces.png differ diff --git a/ui/img/emoji/pizza.png b/ui/img/emoji/pizza.png new file mode 100644 index 0000000..460367d Binary files /dev/null and b/ui/img/emoji/pizza.png differ diff --git a/ui/img/emoji/plus1.png b/ui/img/emoji/plus1.png new file mode 100644 index 0000000..81786c1 Binary files /dev/null and b/ui/img/emoji/plus1.png differ diff --git a/ui/img/emoji/point_down.png b/ui/img/emoji/point_down.png new file mode 100644 index 0000000..658c6d9 Binary files /dev/null and b/ui/img/emoji/point_down.png differ diff --git a/ui/img/emoji/point_left.png b/ui/img/emoji/point_left.png new file mode 100644 index 0000000..38a99b4 Binary files /dev/null and b/ui/img/emoji/point_left.png differ diff --git a/ui/img/emoji/point_right.png b/ui/img/emoji/point_right.png new file mode 100644 index 0000000..6f9f029 Binary files /dev/null and b/ui/img/emoji/point_right.png differ diff --git a/ui/img/emoji/point_up.png b/ui/img/emoji/point_up.png new file mode 100644 index 0000000..01896e2 Binary files /dev/null and b/ui/img/emoji/point_up.png differ diff --git a/ui/img/emoji/point_up_2.png b/ui/img/emoji/point_up_2.png new file mode 100644 index 0000000..1cfe736 Binary files /dev/null and b/ui/img/emoji/point_up_2.png differ diff --git a/ui/img/emoji/police_car.png b/ui/img/emoji/police_car.png new file mode 100644 index 0000000..b8f1727 Binary files /dev/null and b/ui/img/emoji/police_car.png differ diff --git a/ui/img/emoji/poodle.png b/ui/img/emoji/poodle.png new file mode 100644 index 0000000..adac80b Binary files /dev/null and b/ui/img/emoji/poodle.png differ diff --git a/ui/img/emoji/poop.png b/ui/img/emoji/poop.png new file mode 100644 index 0000000..73a4dc8 Binary files /dev/null and b/ui/img/emoji/poop.png differ diff --git a/ui/img/emoji/post_office.png b/ui/img/emoji/post_office.png new file mode 100644 index 0000000..43b59e3 Binary files /dev/null and b/ui/img/emoji/post_office.png differ diff --git a/ui/img/emoji/postal_horn.png b/ui/img/emoji/postal_horn.png new file mode 100644 index 0000000..13a1514 Binary files /dev/null and b/ui/img/emoji/postal_horn.png differ diff --git a/ui/img/emoji/postbox.png b/ui/img/emoji/postbox.png new file mode 100644 index 0000000..ce04b70 Binary files /dev/null and b/ui/img/emoji/postbox.png differ diff --git a/ui/img/emoji/potable_water.png b/ui/img/emoji/potable_water.png new file mode 100644 index 0000000..e9fd560 Binary files /dev/null and b/ui/img/emoji/potable_water.png differ diff --git a/ui/img/emoji/pouch.png b/ui/img/emoji/pouch.png new file mode 100644 index 0000000..dc35ae8 Binary files /dev/null and b/ui/img/emoji/pouch.png differ diff --git a/ui/img/emoji/poultry_leg.png b/ui/img/emoji/poultry_leg.png new file mode 100644 index 0000000..43ad859 Binary files /dev/null and b/ui/img/emoji/poultry_leg.png differ diff --git a/ui/img/emoji/pound.png b/ui/img/emoji/pound.png new file mode 100644 index 0000000..f8be91d Binary files /dev/null and b/ui/img/emoji/pound.png differ diff --git a/ui/img/emoji/pouting_cat.png b/ui/img/emoji/pouting_cat.png new file mode 100644 index 0000000..4325fd4 Binary files /dev/null and b/ui/img/emoji/pouting_cat.png differ diff --git a/ui/img/emoji/pray.png b/ui/img/emoji/pray.png new file mode 100644 index 0000000..f86c992 Binary files /dev/null and b/ui/img/emoji/pray.png differ diff --git a/ui/img/emoji/princess.png b/ui/img/emoji/princess.png new file mode 100644 index 0000000..1ebb2ce Binary files /dev/null and b/ui/img/emoji/princess.png differ diff --git a/ui/img/emoji/punch.png b/ui/img/emoji/punch.png new file mode 100644 index 0000000..277047b Binary files /dev/null and b/ui/img/emoji/punch.png differ diff --git a/ui/img/emoji/purple_heart.png b/ui/img/emoji/purple_heart.png new file mode 100644 index 0000000..d5f8750 Binary files /dev/null and b/ui/img/emoji/purple_heart.png differ diff --git a/ui/img/emoji/purse.png b/ui/img/emoji/purse.png new file mode 100644 index 0000000..8f06a2b Binary files /dev/null and b/ui/img/emoji/purse.png differ diff --git a/ui/img/emoji/pushpin.png b/ui/img/emoji/pushpin.png new file mode 100644 index 0000000..540c4ec Binary files /dev/null and b/ui/img/emoji/pushpin.png differ diff --git a/ui/img/emoji/put_litter_in_its_place.png b/ui/img/emoji/put_litter_in_its_place.png new file mode 100644 index 0000000..c2e350c Binary files /dev/null and b/ui/img/emoji/put_litter_in_its_place.png differ diff --git a/ui/img/emoji/question.png b/ui/img/emoji/question.png new file mode 100644 index 0000000..38cedf5 Binary files /dev/null and b/ui/img/emoji/question.png differ diff --git a/ui/img/emoji/rabbit.png b/ui/img/emoji/rabbit.png new file mode 100644 index 0000000..5cb3ef6 Binary files /dev/null and b/ui/img/emoji/rabbit.png differ diff --git a/ui/img/emoji/rabbit2.png b/ui/img/emoji/rabbit2.png new file mode 100644 index 0000000..a9fd24d Binary files /dev/null and b/ui/img/emoji/rabbit2.png differ diff --git a/ui/img/emoji/racehorse.png b/ui/img/emoji/racehorse.png new file mode 100644 index 0000000..4d09c64 Binary files /dev/null and b/ui/img/emoji/racehorse.png differ diff --git a/ui/img/emoji/radio.png b/ui/img/emoji/radio.png new file mode 100644 index 0000000..ea589ef Binary files /dev/null and b/ui/img/emoji/radio.png differ diff --git a/ui/img/emoji/radio_button.png b/ui/img/emoji/radio_button.png new file mode 100644 index 0000000..63755ee Binary files /dev/null and b/ui/img/emoji/radio_button.png differ diff --git a/ui/img/emoji/rage.png b/ui/img/emoji/rage.png new file mode 100644 index 0000000..c65ddff Binary files /dev/null and b/ui/img/emoji/rage.png differ diff --git a/ui/img/emoji/rage1.png b/ui/img/emoji/rage1.png new file mode 100644 index 0000000..1506ba4 Binary files /dev/null and b/ui/img/emoji/rage1.png differ diff --git a/ui/img/emoji/rage2.png b/ui/img/emoji/rage2.png new file mode 100644 index 0000000..f792e06 Binary files /dev/null and b/ui/img/emoji/rage2.png differ diff --git a/ui/img/emoji/rage3.png b/ui/img/emoji/rage3.png new file mode 100644 index 0000000..58764cb Binary files /dev/null and b/ui/img/emoji/rage3.png differ diff --git a/ui/img/emoji/rage4.png b/ui/img/emoji/rage4.png new file mode 100644 index 0000000..c726c94 Binary files /dev/null and b/ui/img/emoji/rage4.png differ diff --git a/ui/img/emoji/railway_car.png b/ui/img/emoji/railway_car.png new file mode 100644 index 0000000..2236115 Binary files /dev/null and b/ui/img/emoji/railway_car.png differ diff --git a/ui/img/emoji/rainbow.png b/ui/img/emoji/rainbow.png new file mode 100644 index 0000000..6b1faa0 Binary files /dev/null and b/ui/img/emoji/rainbow.png differ diff --git a/ui/img/emoji/raised_hand.png b/ui/img/emoji/raised_hand.png new file mode 100644 index 0000000..5e45c25 Binary files /dev/null and b/ui/img/emoji/raised_hand.png differ diff --git a/ui/img/emoji/raised_hands.png b/ui/img/emoji/raised_hands.png new file mode 100644 index 0000000..e03142b Binary files /dev/null and b/ui/img/emoji/raised_hands.png differ diff --git a/ui/img/emoji/raising_hand.png b/ui/img/emoji/raising_hand.png new file mode 100644 index 0000000..e1741a4 Binary files /dev/null and b/ui/img/emoji/raising_hand.png differ diff --git a/ui/img/emoji/ram.png b/ui/img/emoji/ram.png new file mode 100644 index 0000000..5ea7bfb Binary files /dev/null and b/ui/img/emoji/ram.png differ diff --git a/ui/img/emoji/ramen.png b/ui/img/emoji/ramen.png new file mode 100644 index 0000000..78dc7d5 Binary files /dev/null and b/ui/img/emoji/ramen.png differ diff --git a/ui/img/emoji/rat.png b/ui/img/emoji/rat.png new file mode 100644 index 0000000..fa7dd40 Binary files /dev/null and b/ui/img/emoji/rat.png differ diff --git a/ui/img/emoji/recycle.png b/ui/img/emoji/recycle.png new file mode 100644 index 0000000..99104c0 Binary files /dev/null and b/ui/img/emoji/recycle.png differ diff --git a/ui/img/emoji/red_car.png b/ui/img/emoji/red_car.png new file mode 100644 index 0000000..d70a2f0 Binary files /dev/null and b/ui/img/emoji/red_car.png differ diff --git a/ui/img/emoji/red_circle.png b/ui/img/emoji/red_circle.png new file mode 100644 index 0000000..b391289 Binary files /dev/null and b/ui/img/emoji/red_circle.png differ diff --git a/ui/img/emoji/registered.png b/ui/img/emoji/registered.png new file mode 100644 index 0000000..31c68a8 Binary files /dev/null and b/ui/img/emoji/registered.png differ diff --git a/ui/img/emoji/relaxed.png b/ui/img/emoji/relaxed.png new file mode 100644 index 0000000..bbab82d Binary files /dev/null and b/ui/img/emoji/relaxed.png differ diff --git a/ui/img/emoji/relieved.png b/ui/img/emoji/relieved.png new file mode 100644 index 0000000..fe5629f Binary files /dev/null and b/ui/img/emoji/relieved.png differ diff --git a/ui/img/emoji/repeat.png b/ui/img/emoji/repeat.png new file mode 100644 index 0000000..80113b6 Binary files /dev/null and b/ui/img/emoji/repeat.png differ diff --git a/ui/img/emoji/repeat_one.png b/ui/img/emoji/repeat_one.png new file mode 100644 index 0000000..3c47bcc Binary files /dev/null and b/ui/img/emoji/repeat_one.png differ diff --git a/ui/img/emoji/restroom.png b/ui/img/emoji/restroom.png new file mode 100644 index 0000000..d6c111b Binary files /dev/null and b/ui/img/emoji/restroom.png differ diff --git a/ui/img/emoji/revolving_hearts.png b/ui/img/emoji/revolving_hearts.png new file mode 100644 index 0000000..ea3317c Binary files /dev/null and b/ui/img/emoji/revolving_hearts.png differ diff --git a/ui/img/emoji/rewind.png b/ui/img/emoji/rewind.png new file mode 100644 index 0000000..26289dc Binary files /dev/null and b/ui/img/emoji/rewind.png differ diff --git a/ui/img/emoji/ribbon.png b/ui/img/emoji/ribbon.png new file mode 100644 index 0000000..63ee5ba Binary files /dev/null and b/ui/img/emoji/ribbon.png differ diff --git a/ui/img/emoji/rice.png b/ui/img/emoji/rice.png new file mode 100644 index 0000000..1fd2202 Binary files /dev/null and b/ui/img/emoji/rice.png differ diff --git a/ui/img/emoji/rice_ball.png b/ui/img/emoji/rice_ball.png new file mode 100644 index 0000000..ade7c45 Binary files /dev/null and b/ui/img/emoji/rice_ball.png differ diff --git a/ui/img/emoji/rice_cracker.png b/ui/img/emoji/rice_cracker.png new file mode 100644 index 0000000..954c901 Binary files /dev/null and b/ui/img/emoji/rice_cracker.png differ diff --git a/ui/img/emoji/rice_scene.png b/ui/img/emoji/rice_scene.png new file mode 100644 index 0000000..1436198 Binary files /dev/null and b/ui/img/emoji/rice_scene.png differ diff --git a/ui/img/emoji/ring.png b/ui/img/emoji/ring.png new file mode 100644 index 0000000..8a57fd6 Binary files /dev/null and b/ui/img/emoji/ring.png differ diff --git a/ui/img/emoji/rocket.png b/ui/img/emoji/rocket.png new file mode 100644 index 0000000..783078d Binary files /dev/null and b/ui/img/emoji/rocket.png differ diff --git a/ui/img/emoji/roller_coaster.png b/ui/img/emoji/roller_coaster.png new file mode 100644 index 0000000..9180b98 Binary files /dev/null and b/ui/img/emoji/roller_coaster.png differ diff --git a/ui/img/emoji/rooster.png b/ui/img/emoji/rooster.png new file mode 100644 index 0000000..fab23ad Binary files /dev/null and b/ui/img/emoji/rooster.png differ diff --git a/ui/img/emoji/rose.png b/ui/img/emoji/rose.png new file mode 100644 index 0000000..3479fbc Binary files /dev/null and b/ui/img/emoji/rose.png differ diff --git a/ui/img/emoji/rotating_light.png b/ui/img/emoji/rotating_light.png new file mode 100644 index 0000000..6cf4a77 Binary files /dev/null and b/ui/img/emoji/rotating_light.png differ diff --git a/ui/img/emoji/round_pushpin.png b/ui/img/emoji/round_pushpin.png new file mode 100644 index 0000000..e498e92 Binary files /dev/null and b/ui/img/emoji/round_pushpin.png differ diff --git a/ui/img/emoji/rowboat.png b/ui/img/emoji/rowboat.png new file mode 100644 index 0000000..e370d0f Binary files /dev/null and b/ui/img/emoji/rowboat.png differ diff --git a/ui/img/emoji/ru.png b/ui/img/emoji/ru.png new file mode 100644 index 0000000..55fcf35 Binary files /dev/null and b/ui/img/emoji/ru.png differ diff --git a/ui/img/emoji/rugby_football.png b/ui/img/emoji/rugby_football.png new file mode 100644 index 0000000..f8db67d Binary files /dev/null and b/ui/img/emoji/rugby_football.png differ diff --git a/ui/img/emoji/runner.png b/ui/img/emoji/runner.png new file mode 100644 index 0000000..cb00429 Binary files /dev/null and b/ui/img/emoji/runner.png differ diff --git a/ui/img/emoji/running.png b/ui/img/emoji/running.png new file mode 100644 index 0000000..cb00429 Binary files /dev/null and b/ui/img/emoji/running.png differ diff --git a/ui/img/emoji/running_shirt_with_sash.png b/ui/img/emoji/running_shirt_with_sash.png new file mode 100644 index 0000000..0d68bba Binary files /dev/null and b/ui/img/emoji/running_shirt_with_sash.png differ diff --git a/ui/img/emoji/sa.png b/ui/img/emoji/sa.png new file mode 100644 index 0000000..387f098 Binary files /dev/null and b/ui/img/emoji/sa.png differ diff --git a/ui/img/emoji/sagittarius.png b/ui/img/emoji/sagittarius.png new file mode 100644 index 0000000..8b5435b Binary files /dev/null and b/ui/img/emoji/sagittarius.png differ diff --git a/ui/img/emoji/sailboat.png b/ui/img/emoji/sailboat.png new file mode 100644 index 0000000..ff656dc Binary files /dev/null and b/ui/img/emoji/sailboat.png differ diff --git a/ui/img/emoji/sake.png b/ui/img/emoji/sake.png new file mode 100644 index 0000000..1f69907 Binary files /dev/null and b/ui/img/emoji/sake.png differ diff --git a/ui/img/emoji/sandal.png b/ui/img/emoji/sandal.png new file mode 100644 index 0000000..0bb3f66 Binary files /dev/null and b/ui/img/emoji/sandal.png differ diff --git a/ui/img/emoji/santa.png b/ui/img/emoji/santa.png new file mode 100644 index 0000000..a2240c0 Binary files /dev/null and b/ui/img/emoji/santa.png differ diff --git a/ui/img/emoji/satellite.png b/ui/img/emoji/satellite.png new file mode 100644 index 0000000..3481cc2 Binary files /dev/null and b/ui/img/emoji/satellite.png differ diff --git a/ui/img/emoji/satisfied.png b/ui/img/emoji/satisfied.png new file mode 100644 index 0000000..11c91eb Binary files /dev/null and b/ui/img/emoji/satisfied.png differ diff --git a/ui/img/emoji/saxophone.png b/ui/img/emoji/saxophone.png new file mode 100644 index 0000000..011559a Binary files /dev/null and b/ui/img/emoji/saxophone.png differ diff --git a/ui/img/emoji/school.png b/ui/img/emoji/school.png new file mode 100644 index 0000000..afd922b Binary files /dev/null and b/ui/img/emoji/school.png differ diff --git a/ui/img/emoji/school_satchel.png b/ui/img/emoji/school_satchel.png new file mode 100644 index 0000000..edfb19a Binary files /dev/null and b/ui/img/emoji/school_satchel.png differ diff --git a/ui/img/emoji/scissors.png b/ui/img/emoji/scissors.png new file mode 100644 index 0000000..d99b8ae Binary files /dev/null and b/ui/img/emoji/scissors.png differ diff --git a/ui/img/emoji/scorpius.png b/ui/img/emoji/scorpius.png new file mode 100644 index 0000000..67fcea1 Binary files /dev/null and b/ui/img/emoji/scorpius.png differ diff --git a/ui/img/emoji/scream.png b/ui/img/emoji/scream.png new file mode 100644 index 0000000..9e93c88 Binary files /dev/null and b/ui/img/emoji/scream.png differ diff --git a/ui/img/emoji/scream_cat.png b/ui/img/emoji/scream_cat.png new file mode 100644 index 0000000..d94cd34 Binary files /dev/null and b/ui/img/emoji/scream_cat.png differ diff --git a/ui/img/emoji/scroll.png b/ui/img/emoji/scroll.png new file mode 100644 index 0000000..c5a10e6 Binary files /dev/null and b/ui/img/emoji/scroll.png differ diff --git a/ui/img/emoji/seat.png b/ui/img/emoji/seat.png new file mode 100644 index 0000000..d1cb864 Binary files /dev/null and b/ui/img/emoji/seat.png differ diff --git a/ui/img/emoji/secret.png b/ui/img/emoji/secret.png new file mode 100644 index 0000000..82e383a Binary files /dev/null and b/ui/img/emoji/secret.png differ diff --git a/ui/img/emoji/see_no_evil.png b/ui/img/emoji/see_no_evil.png new file mode 100644 index 0000000..0890a62 Binary files /dev/null and b/ui/img/emoji/see_no_evil.png differ diff --git a/ui/img/emoji/seedling.png b/ui/img/emoji/seedling.png new file mode 100644 index 0000000..2ab0793 Binary files /dev/null and b/ui/img/emoji/seedling.png differ diff --git a/ui/img/emoji/seven.png b/ui/img/emoji/seven.png new file mode 100644 index 0000000..354e89a Binary files /dev/null and b/ui/img/emoji/seven.png differ diff --git a/ui/img/emoji/shaved_ice.png b/ui/img/emoji/shaved_ice.png new file mode 100644 index 0000000..0d0b382 Binary files /dev/null and b/ui/img/emoji/shaved_ice.png differ diff --git a/ui/img/emoji/sheep.png b/ui/img/emoji/sheep.png new file mode 100644 index 0000000..c7277d2 Binary files /dev/null and b/ui/img/emoji/sheep.png differ diff --git a/ui/img/emoji/shell.png b/ui/img/emoji/shell.png new file mode 100644 index 0000000..3145b56 Binary files /dev/null and b/ui/img/emoji/shell.png differ diff --git a/ui/img/emoji/ship.png b/ui/img/emoji/ship.png new file mode 100644 index 0000000..5d2d8b6 Binary files /dev/null and b/ui/img/emoji/ship.png differ diff --git a/ui/img/emoji/shipit.png b/ui/img/emoji/shipit.png new file mode 100644 index 0000000..a58a47f Binary files /dev/null and b/ui/img/emoji/shipit.png differ diff --git a/ui/img/emoji/shirt.png b/ui/img/emoji/shirt.png new file mode 100644 index 0000000..297a6d6 Binary files /dev/null and b/ui/img/emoji/shirt.png differ diff --git a/ui/img/emoji/shit.png b/ui/img/emoji/shit.png new file mode 100644 index 0000000..73a4dc8 Binary files /dev/null and b/ui/img/emoji/shit.png differ diff --git a/ui/img/emoji/shoe.png b/ui/img/emoji/shoe.png new file mode 100644 index 0000000..45b82e6 Binary files /dev/null and b/ui/img/emoji/shoe.png differ diff --git a/ui/img/emoji/shower.png b/ui/img/emoji/shower.png new file mode 100644 index 0000000..0d72ab8 Binary files /dev/null and b/ui/img/emoji/shower.png differ diff --git a/ui/img/emoji/signal_strength.png b/ui/img/emoji/signal_strength.png new file mode 100644 index 0000000..a4bd23e Binary files /dev/null and b/ui/img/emoji/signal_strength.png differ diff --git a/ui/img/emoji/six.png b/ui/img/emoji/six.png new file mode 100644 index 0000000..5688055 Binary files /dev/null and b/ui/img/emoji/six.png differ diff --git a/ui/img/emoji/six_pointed_star.png b/ui/img/emoji/six_pointed_star.png new file mode 100644 index 0000000..c11af14 Binary files /dev/null and b/ui/img/emoji/six_pointed_star.png differ diff --git a/ui/img/emoji/ski.png b/ui/img/emoji/ski.png new file mode 100644 index 0000000..98f5cb0 Binary files /dev/null and b/ui/img/emoji/ski.png differ diff --git a/ui/img/emoji/skull.png b/ui/img/emoji/skull.png new file mode 100644 index 0000000..bd4ee38 Binary files /dev/null and b/ui/img/emoji/skull.png differ diff --git a/ui/img/emoji/sleeping.png b/ui/img/emoji/sleeping.png new file mode 100644 index 0000000..093b852 Binary files /dev/null and b/ui/img/emoji/sleeping.png differ diff --git a/ui/img/emoji/sleepy.png b/ui/img/emoji/sleepy.png new file mode 100644 index 0000000..df4f55e Binary files /dev/null and b/ui/img/emoji/sleepy.png differ diff --git a/ui/img/emoji/slot_machine.png b/ui/img/emoji/slot_machine.png new file mode 100644 index 0000000..26f1148 Binary files /dev/null and b/ui/img/emoji/slot_machine.png differ diff --git a/ui/img/emoji/small_blue_diamond.png b/ui/img/emoji/small_blue_diamond.png new file mode 100644 index 0000000..8cd4920 Binary files /dev/null and b/ui/img/emoji/small_blue_diamond.png differ diff --git a/ui/img/emoji/small_orange_diamond.png b/ui/img/emoji/small_orange_diamond.png new file mode 100644 index 0000000..04941d3 Binary files /dev/null and b/ui/img/emoji/small_orange_diamond.png differ diff --git a/ui/img/emoji/small_red_triangle.png b/ui/img/emoji/small_red_triangle.png new file mode 100644 index 0000000..8c4428d Binary files /dev/null and b/ui/img/emoji/small_red_triangle.png differ diff --git a/ui/img/emoji/small_red_triangle_down.png b/ui/img/emoji/small_red_triangle_down.png new file mode 100644 index 0000000..94832f0 Binary files /dev/null and b/ui/img/emoji/small_red_triangle_down.png differ diff --git a/ui/img/emoji/smile.png b/ui/img/emoji/smile.png new file mode 100644 index 0000000..81a8396 Binary files /dev/null and b/ui/img/emoji/smile.png differ diff --git a/ui/img/emoji/smile_cat.png b/ui/img/emoji/smile_cat.png new file mode 100644 index 0000000..ad333ba Binary files /dev/null and b/ui/img/emoji/smile_cat.png differ diff --git a/ui/img/emoji/smiley.png b/ui/img/emoji/smiley.png new file mode 100644 index 0000000..77b581d Binary files /dev/null and b/ui/img/emoji/smiley.png differ diff --git a/ui/img/emoji/smiley_cat.png b/ui/img/emoji/smiley_cat.png new file mode 100644 index 0000000..dbf1b02 Binary files /dev/null and b/ui/img/emoji/smiley_cat.png differ diff --git a/ui/img/emoji/smiling_imp.png b/ui/img/emoji/smiling_imp.png new file mode 100644 index 0000000..d904049 Binary files /dev/null and b/ui/img/emoji/smiling_imp.png differ diff --git a/ui/img/emoji/smirk.png b/ui/img/emoji/smirk.png new file mode 100644 index 0000000..bc6e508 Binary files /dev/null and b/ui/img/emoji/smirk.png differ diff --git a/ui/img/emoji/smirk_cat.png b/ui/img/emoji/smirk_cat.png new file mode 100644 index 0000000..351565e Binary files /dev/null and b/ui/img/emoji/smirk_cat.png differ diff --git a/ui/img/emoji/smoking.png b/ui/img/emoji/smoking.png new file mode 100644 index 0000000..4aad6cb Binary files /dev/null and b/ui/img/emoji/smoking.png differ diff --git a/ui/img/emoji/snail.png b/ui/img/emoji/snail.png new file mode 100644 index 0000000..e75e69a Binary files /dev/null and b/ui/img/emoji/snail.png differ diff --git a/ui/img/emoji/snake.png b/ui/img/emoji/snake.png new file mode 100644 index 0000000..ef58933 Binary files /dev/null and b/ui/img/emoji/snake.png differ diff --git a/ui/img/emoji/snowboarder.png b/ui/img/emoji/snowboarder.png new file mode 100644 index 0000000..aeda5c8 Binary files /dev/null and b/ui/img/emoji/snowboarder.png differ diff --git a/ui/img/emoji/snowflake.png b/ui/img/emoji/snowflake.png new file mode 100644 index 0000000..54b68ff Binary files /dev/null and b/ui/img/emoji/snowflake.png differ diff --git a/ui/img/emoji/snowman.png b/ui/img/emoji/snowman.png new file mode 100644 index 0000000..a97902e Binary files /dev/null and b/ui/img/emoji/snowman.png differ diff --git a/ui/img/emoji/sob.png b/ui/img/emoji/sob.png new file mode 100644 index 0000000..1561df9 Binary files /dev/null and b/ui/img/emoji/sob.png differ diff --git a/ui/img/emoji/soccer.png b/ui/img/emoji/soccer.png new file mode 100644 index 0000000..1e118b5 Binary files /dev/null and b/ui/img/emoji/soccer.png differ diff --git a/ui/img/emoji/soon.png b/ui/img/emoji/soon.png new file mode 100644 index 0000000..2cf46df Binary files /dev/null and b/ui/img/emoji/soon.png differ diff --git a/ui/img/emoji/sos.png b/ui/img/emoji/sos.png new file mode 100644 index 0000000..e3e16ef Binary files /dev/null and b/ui/img/emoji/sos.png differ diff --git a/ui/img/emoji/sound.png b/ui/img/emoji/sound.png new file mode 100644 index 0000000..6aa4dbf Binary files /dev/null and b/ui/img/emoji/sound.png differ diff --git a/ui/img/emoji/space_invader.png b/ui/img/emoji/space_invader.png new file mode 100644 index 0000000..3840491 Binary files /dev/null and b/ui/img/emoji/space_invader.png differ diff --git a/ui/img/emoji/spades.png b/ui/img/emoji/spades.png new file mode 100644 index 0000000..133a1ab Binary files /dev/null and b/ui/img/emoji/spades.png differ diff --git a/ui/img/emoji/spaghetti.png b/ui/img/emoji/spaghetti.png new file mode 100644 index 0000000..08de243 Binary files /dev/null and b/ui/img/emoji/spaghetti.png differ diff --git a/ui/img/emoji/sparkler.png b/ui/img/emoji/sparkler.png new file mode 100644 index 0000000..4aabd7e Binary files /dev/null and b/ui/img/emoji/sparkler.png differ diff --git a/ui/img/emoji/sparkles.png b/ui/img/emoji/sparkles.png new file mode 100644 index 0000000..51307bc Binary files /dev/null and b/ui/img/emoji/sparkles.png differ diff --git a/ui/img/emoji/sparkling_heart.png b/ui/img/emoji/sparkling_heart.png new file mode 100644 index 0000000..64ac066 Binary files /dev/null and b/ui/img/emoji/sparkling_heart.png differ diff --git a/ui/img/emoji/speak_no_evil.png b/ui/img/emoji/speak_no_evil.png new file mode 100644 index 0000000..87944c4 Binary files /dev/null and b/ui/img/emoji/speak_no_evil.png differ diff --git a/ui/img/emoji/speaker.png b/ui/img/emoji/speaker.png new file mode 100644 index 0000000..470476e Binary files /dev/null and b/ui/img/emoji/speaker.png differ diff --git a/ui/img/emoji/speech_balloon.png b/ui/img/emoji/speech_balloon.png new file mode 100644 index 0000000..2896c27 Binary files /dev/null and b/ui/img/emoji/speech_balloon.png differ diff --git a/ui/img/emoji/speedboat.png b/ui/img/emoji/speedboat.png new file mode 100644 index 0000000..da6689b Binary files /dev/null and b/ui/img/emoji/speedboat.png differ diff --git a/ui/img/emoji/squirrel.png b/ui/img/emoji/squirrel.png new file mode 100644 index 0000000..a58a47f Binary files /dev/null and b/ui/img/emoji/squirrel.png differ diff --git a/ui/img/emoji/star.png b/ui/img/emoji/star.png new file mode 100644 index 0000000..1bfddc8 Binary files /dev/null and b/ui/img/emoji/star.png differ diff --git a/ui/img/emoji/star2.png b/ui/img/emoji/star2.png new file mode 100644 index 0000000..8b40ff4 Binary files /dev/null and b/ui/img/emoji/star2.png differ diff --git a/ui/img/emoji/stars.png b/ui/img/emoji/stars.png new file mode 100644 index 0000000..097a842 Binary files /dev/null and b/ui/img/emoji/stars.png differ diff --git a/ui/img/emoji/station.png b/ui/img/emoji/station.png new file mode 100644 index 0000000..e77daa8 Binary files /dev/null and b/ui/img/emoji/station.png differ diff --git a/ui/img/emoji/statue_of_liberty.png b/ui/img/emoji/statue_of_liberty.png new file mode 100644 index 0000000..9ad9028 Binary files /dev/null and b/ui/img/emoji/statue_of_liberty.png differ diff --git a/ui/img/emoji/steam_locomotive.png b/ui/img/emoji/steam_locomotive.png new file mode 100644 index 0000000..5495077 Binary files /dev/null and b/ui/img/emoji/steam_locomotive.png differ diff --git a/ui/img/emoji/stew.png b/ui/img/emoji/stew.png new file mode 100644 index 0000000..e9687f9 Binary files /dev/null and b/ui/img/emoji/stew.png differ diff --git a/ui/img/emoji/straight_ruler.png b/ui/img/emoji/straight_ruler.png new file mode 100644 index 0000000..d96658e Binary files /dev/null and b/ui/img/emoji/straight_ruler.png differ diff --git a/ui/img/emoji/strawberry.png b/ui/img/emoji/strawberry.png new file mode 100644 index 0000000..13eb827 Binary files /dev/null and b/ui/img/emoji/strawberry.png differ diff --git a/ui/img/emoji/stuck_out_tongue.png b/ui/img/emoji/stuck_out_tongue.png new file mode 100644 index 0000000..fa7b58e Binary files /dev/null and b/ui/img/emoji/stuck_out_tongue.png differ diff --git a/ui/img/emoji/stuck_out_tongue_closed_eyes.png b/ui/img/emoji/stuck_out_tongue_closed_eyes.png new file mode 100644 index 0000000..333716e Binary files /dev/null and b/ui/img/emoji/stuck_out_tongue_closed_eyes.png differ diff --git a/ui/img/emoji/stuck_out_tongue_winking_eye.png b/ui/img/emoji/stuck_out_tongue_winking_eye.png new file mode 100644 index 0000000..6ae9d49 Binary files /dev/null and b/ui/img/emoji/stuck_out_tongue_winking_eye.png differ diff --git a/ui/img/emoji/sun_with_face.png b/ui/img/emoji/sun_with_face.png new file mode 100644 index 0000000..ee27663 Binary files /dev/null and b/ui/img/emoji/sun_with_face.png differ diff --git a/ui/img/emoji/sunflower.png b/ui/img/emoji/sunflower.png new file mode 100644 index 0000000..d9bad19 Binary files /dev/null and b/ui/img/emoji/sunflower.png differ diff --git a/ui/img/emoji/sunglasses.png b/ui/img/emoji/sunglasses.png new file mode 100644 index 0000000..f2e5247 Binary files /dev/null and b/ui/img/emoji/sunglasses.png differ diff --git a/ui/img/emoji/sunny.png b/ui/img/emoji/sunny.png new file mode 100644 index 0000000..d23c095 Binary files /dev/null and b/ui/img/emoji/sunny.png differ diff --git a/ui/img/emoji/sunrise.png b/ui/img/emoji/sunrise.png new file mode 100644 index 0000000..ec58dcc Binary files /dev/null and b/ui/img/emoji/sunrise.png differ diff --git a/ui/img/emoji/sunrise_over_mountains.png b/ui/img/emoji/sunrise_over_mountains.png new file mode 100644 index 0000000..ebc3db1 Binary files /dev/null and b/ui/img/emoji/sunrise_over_mountains.png differ diff --git a/ui/img/emoji/surfer.png b/ui/img/emoji/surfer.png new file mode 100644 index 0000000..b067e8c Binary files /dev/null and b/ui/img/emoji/surfer.png differ diff --git a/ui/img/emoji/sushi.png b/ui/img/emoji/sushi.png new file mode 100644 index 0000000..0d179bd Binary files /dev/null and b/ui/img/emoji/sushi.png differ diff --git a/ui/img/emoji/suspect.png b/ui/img/emoji/suspect.png new file mode 100644 index 0000000..58e8921 Binary files /dev/null and b/ui/img/emoji/suspect.png differ diff --git a/ui/img/emoji/suspension_railway.png b/ui/img/emoji/suspension_railway.png new file mode 100644 index 0000000..aaa45f6 Binary files /dev/null and b/ui/img/emoji/suspension_railway.png differ diff --git a/ui/img/emoji/sweat.png b/ui/img/emoji/sweat.png new file mode 100644 index 0000000..e894b76 Binary files /dev/null and b/ui/img/emoji/sweat.png differ diff --git a/ui/img/emoji/sweat_drops.png b/ui/img/emoji/sweat_drops.png new file mode 100644 index 0000000..a83b3e9 Binary files /dev/null and b/ui/img/emoji/sweat_drops.png differ diff --git a/ui/img/emoji/sweat_smile.png b/ui/img/emoji/sweat_smile.png new file mode 100644 index 0000000..3903f71 Binary files /dev/null and b/ui/img/emoji/sweat_smile.png differ diff --git a/ui/img/emoji/sweet_potato.png b/ui/img/emoji/sweet_potato.png new file mode 100644 index 0000000..cde7880 Binary files /dev/null and b/ui/img/emoji/sweet_potato.png differ diff --git a/ui/img/emoji/swimmer.png b/ui/img/emoji/swimmer.png new file mode 100644 index 0000000..d3878a0 Binary files /dev/null and b/ui/img/emoji/swimmer.png differ diff --git a/ui/img/emoji/symbols.png b/ui/img/emoji/symbols.png new file mode 100644 index 0000000..16bc1da Binary files /dev/null and b/ui/img/emoji/symbols.png differ diff --git a/ui/img/emoji/syringe.png b/ui/img/emoji/syringe.png new file mode 100644 index 0000000..36aa8fe Binary files /dev/null and b/ui/img/emoji/syringe.png differ diff --git a/ui/img/emoji/tada.png b/ui/img/emoji/tada.png new file mode 100644 index 0000000..7411b52 Binary files /dev/null and b/ui/img/emoji/tada.png differ diff --git a/ui/img/emoji/tanabata_tree.png b/ui/img/emoji/tanabata_tree.png new file mode 100644 index 0000000..6dea4b2 Binary files /dev/null and b/ui/img/emoji/tanabata_tree.png differ diff --git a/ui/img/emoji/tangerine.png b/ui/img/emoji/tangerine.png new file mode 100644 index 0000000..fc9d4f8 Binary files /dev/null and b/ui/img/emoji/tangerine.png differ diff --git a/ui/img/emoji/taurus.png b/ui/img/emoji/taurus.png new file mode 100644 index 0000000..6af582f Binary files /dev/null and b/ui/img/emoji/taurus.png differ diff --git a/ui/img/emoji/taxi.png b/ui/img/emoji/taxi.png new file mode 100644 index 0000000..60a50d3 Binary files /dev/null and b/ui/img/emoji/taxi.png differ diff --git a/ui/img/emoji/tea.png b/ui/img/emoji/tea.png new file mode 100644 index 0000000..3ece0b7 Binary files /dev/null and b/ui/img/emoji/tea.png differ diff --git a/ui/img/emoji/telephone.png b/ui/img/emoji/telephone.png new file mode 100644 index 0000000..87d2559 Binary files /dev/null and b/ui/img/emoji/telephone.png differ diff --git a/ui/img/emoji/telephone_receiver.png b/ui/img/emoji/telephone_receiver.png new file mode 100644 index 0000000..36e21e0 Binary files /dev/null and b/ui/img/emoji/telephone_receiver.png differ diff --git a/ui/img/emoji/telescope.png b/ui/img/emoji/telescope.png new file mode 100644 index 0000000..98e5755 Binary files /dev/null and b/ui/img/emoji/telescope.png differ diff --git a/ui/img/emoji/tennis.png b/ui/img/emoji/tennis.png new file mode 100644 index 0000000..278d904 Binary files /dev/null and b/ui/img/emoji/tennis.png differ diff --git a/ui/img/emoji/tent.png b/ui/img/emoji/tent.png new file mode 100644 index 0000000..5c0d20e Binary files /dev/null and b/ui/img/emoji/tent.png differ diff --git a/ui/img/emoji/thought_balloon.png b/ui/img/emoji/thought_balloon.png new file mode 100644 index 0000000..febe30d Binary files /dev/null and b/ui/img/emoji/thought_balloon.png differ diff --git a/ui/img/emoji/three.png b/ui/img/emoji/three.png new file mode 100644 index 0000000..55644c9 Binary files /dev/null and b/ui/img/emoji/three.png differ diff --git a/ui/img/emoji/thumbsdown.png b/ui/img/emoji/thumbsdown.png new file mode 100644 index 0000000..41c6b82 Binary files /dev/null and b/ui/img/emoji/thumbsdown.png differ diff --git a/ui/img/emoji/thumbsup.png b/ui/img/emoji/thumbsup.png new file mode 100644 index 0000000..81786c1 Binary files /dev/null and b/ui/img/emoji/thumbsup.png differ diff --git a/ui/img/emoji/ticket.png b/ui/img/emoji/ticket.png new file mode 100644 index 0000000..cdacf1a Binary files /dev/null and b/ui/img/emoji/ticket.png differ diff --git a/ui/img/emoji/tiger.png b/ui/img/emoji/tiger.png new file mode 100644 index 0000000..d6cc84a Binary files /dev/null and b/ui/img/emoji/tiger.png differ diff --git a/ui/img/emoji/tiger2.png b/ui/img/emoji/tiger2.png new file mode 100644 index 0000000..b0c7d8d Binary files /dev/null and b/ui/img/emoji/tiger2.png differ diff --git a/ui/img/emoji/tired_face.png b/ui/img/emoji/tired_face.png new file mode 100644 index 0000000..77b7834 Binary files /dev/null and b/ui/img/emoji/tired_face.png differ diff --git a/ui/img/emoji/tm.png b/ui/img/emoji/tm.png new file mode 100644 index 0000000..c7dec75 Binary files /dev/null and b/ui/img/emoji/tm.png differ diff --git a/ui/img/emoji/toilet.png b/ui/img/emoji/toilet.png new file mode 100644 index 0000000..e5cc411 Binary files /dev/null and b/ui/img/emoji/toilet.png differ diff --git a/ui/img/emoji/tokyo_tower.png b/ui/img/emoji/tokyo_tower.png new file mode 100644 index 0000000..e1cbd7a Binary files /dev/null and b/ui/img/emoji/tokyo_tower.png differ diff --git a/ui/img/emoji/tomato.png b/ui/img/emoji/tomato.png new file mode 100644 index 0000000..a129700 Binary files /dev/null and b/ui/img/emoji/tomato.png differ diff --git a/ui/img/emoji/tongue.png b/ui/img/emoji/tongue.png new file mode 100644 index 0000000..b0bab12 Binary files /dev/null and b/ui/img/emoji/tongue.png differ diff --git a/ui/img/emoji/top.png b/ui/img/emoji/top.png new file mode 100644 index 0000000..5aa4dd4 Binary files /dev/null and b/ui/img/emoji/top.png differ diff --git a/ui/img/emoji/tophat.png b/ui/img/emoji/tophat.png new file mode 100644 index 0000000..7d27134 Binary files /dev/null and b/ui/img/emoji/tophat.png differ diff --git a/ui/img/emoji/tractor.png b/ui/img/emoji/tractor.png new file mode 100644 index 0000000..058fd3e Binary files /dev/null and b/ui/img/emoji/tractor.png differ diff --git a/ui/img/emoji/traffic_light.png b/ui/img/emoji/traffic_light.png new file mode 100644 index 0000000..1facb27 Binary files /dev/null and b/ui/img/emoji/traffic_light.png differ diff --git a/ui/img/emoji/train.png b/ui/img/emoji/train.png new file mode 100644 index 0000000..3202d80 Binary files /dev/null and b/ui/img/emoji/train.png differ diff --git a/ui/img/emoji/train2.png b/ui/img/emoji/train2.png new file mode 100644 index 0000000..9c0d3ab Binary files /dev/null and b/ui/img/emoji/train2.png differ diff --git a/ui/img/emoji/tram.png b/ui/img/emoji/tram.png new file mode 100644 index 0000000..5eb29fb Binary files /dev/null and b/ui/img/emoji/tram.png differ diff --git a/ui/img/emoji/triangular_flag_on_post.png b/ui/img/emoji/triangular_flag_on_post.png new file mode 100644 index 0000000..f9a3f32 Binary files /dev/null and b/ui/img/emoji/triangular_flag_on_post.png differ diff --git a/ui/img/emoji/triangular_ruler.png b/ui/img/emoji/triangular_ruler.png new file mode 100644 index 0000000..383677c Binary files /dev/null and b/ui/img/emoji/triangular_ruler.png differ diff --git a/ui/img/emoji/trident.png b/ui/img/emoji/trident.png new file mode 100644 index 0000000..d79a7b4 Binary files /dev/null and b/ui/img/emoji/trident.png differ diff --git a/ui/img/emoji/triumph.png b/ui/img/emoji/triumph.png new file mode 100644 index 0000000..92f93bd Binary files /dev/null and b/ui/img/emoji/triumph.png differ diff --git a/ui/img/emoji/trolleybus.png b/ui/img/emoji/trolleybus.png new file mode 100644 index 0000000..b9740a5 Binary files /dev/null and b/ui/img/emoji/trolleybus.png differ diff --git a/ui/img/emoji/trollface.png b/ui/img/emoji/trollface.png new file mode 100644 index 0000000..119d77e Binary files /dev/null and b/ui/img/emoji/trollface.png differ diff --git a/ui/img/emoji/trophy.png b/ui/img/emoji/trophy.png new file mode 100644 index 0000000..95d3b63 Binary files /dev/null and b/ui/img/emoji/trophy.png differ diff --git a/ui/img/emoji/tropical_drink.png b/ui/img/emoji/tropical_drink.png new file mode 100644 index 0000000..55ca9ee Binary files /dev/null and b/ui/img/emoji/tropical_drink.png differ diff --git a/ui/img/emoji/tropical_fish.png b/ui/img/emoji/tropical_fish.png new file mode 100644 index 0000000..a6d7349 Binary files /dev/null and b/ui/img/emoji/tropical_fish.png differ diff --git a/ui/img/emoji/truck.png b/ui/img/emoji/truck.png new file mode 100644 index 0000000..3f25ba1 Binary files /dev/null and b/ui/img/emoji/truck.png differ diff --git a/ui/img/emoji/trumpet.png b/ui/img/emoji/trumpet.png new file mode 100644 index 0000000..c84cfb1 Binary files /dev/null and b/ui/img/emoji/trumpet.png differ diff --git a/ui/img/emoji/tshirt.png b/ui/img/emoji/tshirt.png new file mode 100644 index 0000000..297a6d6 Binary files /dev/null and b/ui/img/emoji/tshirt.png differ diff --git a/ui/img/emoji/tulip.png b/ui/img/emoji/tulip.png new file mode 100644 index 0000000..b3ee110 Binary files /dev/null and b/ui/img/emoji/tulip.png differ diff --git a/ui/img/emoji/turtle.png b/ui/img/emoji/turtle.png new file mode 100644 index 0000000..04d1d96 Binary files /dev/null and b/ui/img/emoji/turtle.png differ diff --git a/ui/img/emoji/tv.png b/ui/img/emoji/tv.png new file mode 100644 index 0000000..803dc3d Binary files /dev/null and b/ui/img/emoji/tv.png differ diff --git a/ui/img/emoji/twisted_rightwards_arrows.png b/ui/img/emoji/twisted_rightwards_arrows.png new file mode 100644 index 0000000..25cde18 Binary files /dev/null and b/ui/img/emoji/twisted_rightwards_arrows.png differ diff --git a/ui/img/emoji/two.png b/ui/img/emoji/two.png new file mode 100644 index 0000000..c191f8a Binary files /dev/null and b/ui/img/emoji/two.png differ diff --git a/ui/img/emoji/two_hearts.png b/ui/img/emoji/two_hearts.png new file mode 100644 index 0000000..b189e9a Binary files /dev/null and b/ui/img/emoji/two_hearts.png differ diff --git a/ui/img/emoji/two_men_holding_hands.png b/ui/img/emoji/two_men_holding_hands.png new file mode 100644 index 0000000..d1099f2 Binary files /dev/null and b/ui/img/emoji/two_men_holding_hands.png differ diff --git a/ui/img/emoji/two_women_holding_hands.png b/ui/img/emoji/two_women_holding_hands.png new file mode 100644 index 0000000..619646c Binary files /dev/null and b/ui/img/emoji/two_women_holding_hands.png differ diff --git a/ui/img/emoji/u5272.png b/ui/img/emoji/u5272.png new file mode 100644 index 0000000..2148253 Binary files /dev/null and b/ui/img/emoji/u5272.png differ diff --git a/ui/img/emoji/u5408.png b/ui/img/emoji/u5408.png new file mode 100644 index 0000000..03ab0d8 Binary files /dev/null and b/ui/img/emoji/u5408.png differ diff --git a/ui/img/emoji/u55b6.png b/ui/img/emoji/u55b6.png new file mode 100644 index 0000000..ba946d3 Binary files /dev/null and b/ui/img/emoji/u55b6.png differ diff --git a/ui/img/emoji/u6307.png b/ui/img/emoji/u6307.png new file mode 100644 index 0000000..6557f56 Binary files /dev/null and b/ui/img/emoji/u6307.png differ diff --git a/ui/img/emoji/u6708.png b/ui/img/emoji/u6708.png new file mode 100644 index 0000000..e4dfe5a Binary files /dev/null and b/ui/img/emoji/u6708.png differ diff --git a/ui/img/emoji/u6709.png b/ui/img/emoji/u6709.png new file mode 100644 index 0000000..cd8fb3f Binary files /dev/null and b/ui/img/emoji/u6709.png differ diff --git a/ui/img/emoji/u6e80.png b/ui/img/emoji/u6e80.png new file mode 100644 index 0000000..5df1cb8 Binary files /dev/null and b/ui/img/emoji/u6e80.png differ diff --git a/ui/img/emoji/u7121.png b/ui/img/emoji/u7121.png new file mode 100644 index 0000000..25f694e Binary files /dev/null and b/ui/img/emoji/u7121.png differ diff --git a/ui/img/emoji/u7533.png b/ui/img/emoji/u7533.png new file mode 100644 index 0000000..fc4a990 Binary files /dev/null and b/ui/img/emoji/u7533.png differ diff --git a/ui/img/emoji/u7981.png b/ui/img/emoji/u7981.png new file mode 100644 index 0000000..f550a57 Binary files /dev/null and b/ui/img/emoji/u7981.png differ diff --git a/ui/img/emoji/u7a7a.png b/ui/img/emoji/u7a7a.png new file mode 100644 index 0000000..c05f5cf Binary files /dev/null and b/ui/img/emoji/u7a7a.png differ diff --git a/ui/img/emoji/uk.png b/ui/img/emoji/uk.png new file mode 100644 index 0000000..2a62c7a Binary files /dev/null and b/ui/img/emoji/uk.png differ diff --git a/ui/img/emoji/umbrella.png b/ui/img/emoji/umbrella.png new file mode 100644 index 0000000..1db722f Binary files /dev/null and b/ui/img/emoji/umbrella.png differ diff --git a/ui/img/emoji/unamused.png b/ui/img/emoji/unamused.png new file mode 100644 index 0000000..3722e6f Binary files /dev/null and b/ui/img/emoji/unamused.png differ diff --git a/ui/img/emoji/underage.png b/ui/img/emoji/underage.png new file mode 100644 index 0000000..a789b3c Binary files /dev/null and b/ui/img/emoji/underage.png differ diff --git a/ui/img/emoji/unlock.png b/ui/img/emoji/unlock.png new file mode 100644 index 0000000..22b429c Binary files /dev/null and b/ui/img/emoji/unlock.png differ diff --git a/ui/img/emoji/up.png b/ui/img/emoji/up.png new file mode 100644 index 0000000..829219a Binary files /dev/null and b/ui/img/emoji/up.png differ diff --git a/ui/img/emoji/us.png b/ui/img/emoji/us.png new file mode 100644 index 0000000..3813766 Binary files /dev/null and b/ui/img/emoji/us.png differ diff --git a/ui/img/emoji/v.png b/ui/img/emoji/v.png new file mode 100644 index 0000000..f61267c Binary files /dev/null and b/ui/img/emoji/v.png differ diff --git a/ui/img/emoji/vertical_traffic_light.png b/ui/img/emoji/vertical_traffic_light.png new file mode 100644 index 0000000..7a5ba35 Binary files /dev/null and b/ui/img/emoji/vertical_traffic_light.png differ diff --git a/ui/img/emoji/vhs.png b/ui/img/emoji/vhs.png new file mode 100644 index 0000000..881081c Binary files /dev/null and b/ui/img/emoji/vhs.png differ diff --git a/ui/img/emoji/vibration_mode.png b/ui/img/emoji/vibration_mode.png new file mode 100644 index 0000000..a716e96 Binary files /dev/null and b/ui/img/emoji/vibration_mode.png differ diff --git a/ui/img/emoji/video_camera.png b/ui/img/emoji/video_camera.png new file mode 100644 index 0000000..274cecd Binary files /dev/null and b/ui/img/emoji/video_camera.png differ diff --git a/ui/img/emoji/video_game.png b/ui/img/emoji/video_game.png new file mode 100644 index 0000000..e265a3b Binary files /dev/null and b/ui/img/emoji/video_game.png differ diff --git a/ui/img/emoji/violin.png b/ui/img/emoji/violin.png new file mode 100644 index 0000000..69347b5 Binary files /dev/null and b/ui/img/emoji/violin.png differ diff --git a/ui/img/emoji/virgo.png b/ui/img/emoji/virgo.png new file mode 100644 index 0000000..72e1763 Binary files /dev/null and b/ui/img/emoji/virgo.png differ diff --git a/ui/img/emoji/volcano.png b/ui/img/emoji/volcano.png new file mode 100644 index 0000000..9b43453 Binary files /dev/null and b/ui/img/emoji/volcano.png differ diff --git a/ui/img/emoji/vs.png b/ui/img/emoji/vs.png new file mode 100644 index 0000000..8636388 Binary files /dev/null and b/ui/img/emoji/vs.png differ diff --git a/ui/img/emoji/walking.png b/ui/img/emoji/walking.png new file mode 100644 index 0000000..52bc038 Binary files /dev/null and b/ui/img/emoji/walking.png differ diff --git a/ui/img/emoji/waning_crescent_moon.png b/ui/img/emoji/waning_crescent_moon.png new file mode 100644 index 0000000..3038778 Binary files /dev/null and b/ui/img/emoji/waning_crescent_moon.png differ diff --git a/ui/img/emoji/waning_gibbous_moon.png b/ui/img/emoji/waning_gibbous_moon.png new file mode 100644 index 0000000..5100990 Binary files /dev/null and b/ui/img/emoji/waning_gibbous_moon.png differ diff --git a/ui/img/emoji/warning.png b/ui/img/emoji/warning.png new file mode 100644 index 0000000..db6f96f Binary files /dev/null and b/ui/img/emoji/warning.png differ diff --git a/ui/img/emoji/watch.png b/ui/img/emoji/watch.png new file mode 100644 index 0000000..d503bb8 Binary files /dev/null and b/ui/img/emoji/watch.png differ diff --git a/ui/img/emoji/water_buffalo.png b/ui/img/emoji/water_buffalo.png new file mode 100644 index 0000000..3bcde3e Binary files /dev/null and b/ui/img/emoji/water_buffalo.png differ diff --git a/ui/img/emoji/watermelon.png b/ui/img/emoji/watermelon.png new file mode 100644 index 0000000..fc212be Binary files /dev/null and b/ui/img/emoji/watermelon.png differ diff --git a/ui/img/emoji/wave.png b/ui/img/emoji/wave.png new file mode 100644 index 0000000..56e6e82 Binary files /dev/null and b/ui/img/emoji/wave.png differ diff --git a/ui/img/emoji/wavy_dash.png b/ui/img/emoji/wavy_dash.png new file mode 100644 index 0000000..5a74e5c Binary files /dev/null and b/ui/img/emoji/wavy_dash.png differ diff --git a/ui/img/emoji/waxing_crescent_moon.png b/ui/img/emoji/waxing_crescent_moon.png new file mode 100644 index 0000000..c8f13dd Binary files /dev/null and b/ui/img/emoji/waxing_crescent_moon.png differ diff --git a/ui/img/emoji/waxing_gibbous_moon.png b/ui/img/emoji/waxing_gibbous_moon.png new file mode 100644 index 0000000..54e7ec6 Binary files /dev/null and b/ui/img/emoji/waxing_gibbous_moon.png differ diff --git a/ui/img/emoji/wc.png b/ui/img/emoji/wc.png new file mode 100644 index 0000000..dfe84d2 Binary files /dev/null and b/ui/img/emoji/wc.png differ diff --git a/ui/img/emoji/weary.png b/ui/img/emoji/weary.png new file mode 100644 index 0000000..0c54754 Binary files /dev/null and b/ui/img/emoji/weary.png differ diff --git a/ui/img/emoji/wedding.png b/ui/img/emoji/wedding.png new file mode 100644 index 0000000..ead19d5 Binary files /dev/null and b/ui/img/emoji/wedding.png differ diff --git a/ui/img/emoji/whale.png b/ui/img/emoji/whale.png new file mode 100644 index 0000000..5bb113e Binary files /dev/null and b/ui/img/emoji/whale.png differ diff --git a/ui/img/emoji/whale2.png b/ui/img/emoji/whale2.png new file mode 100644 index 0000000..0ef4ea9 Binary files /dev/null and b/ui/img/emoji/whale2.png differ diff --git a/ui/img/emoji/wheelchair.png b/ui/img/emoji/wheelchair.png new file mode 100644 index 0000000..eddcdd7 Binary files /dev/null and b/ui/img/emoji/wheelchair.png differ diff --git a/ui/img/emoji/white_check_mark.png b/ui/img/emoji/white_check_mark.png new file mode 100644 index 0000000..61dc058 Binary files /dev/null and b/ui/img/emoji/white_check_mark.png differ diff --git a/ui/img/emoji/white_circle.png b/ui/img/emoji/white_circle.png new file mode 100644 index 0000000..3f648d1 Binary files /dev/null and b/ui/img/emoji/white_circle.png differ diff --git a/ui/img/emoji/white_flower.png b/ui/img/emoji/white_flower.png new file mode 100644 index 0000000..c0929d0 Binary files /dev/null and b/ui/img/emoji/white_flower.png differ diff --git a/ui/img/emoji/white_large_square.png b/ui/img/emoji/white_large_square.png new file mode 100644 index 0000000..60cb19a Binary files /dev/null and b/ui/img/emoji/white_large_square.png differ diff --git a/ui/img/emoji/white_square_button.png b/ui/img/emoji/white_square_button.png new file mode 100644 index 0000000..ad54d55 Binary files /dev/null and b/ui/img/emoji/white_square_button.png differ diff --git a/ui/img/emoji/wind_chime.png b/ui/img/emoji/wind_chime.png new file mode 100644 index 0000000..efacf5d Binary files /dev/null and b/ui/img/emoji/wind_chime.png differ diff --git a/ui/img/emoji/wine_glass.png b/ui/img/emoji/wine_glass.png new file mode 100644 index 0000000..82b0f00 Binary files /dev/null and b/ui/img/emoji/wine_glass.png differ diff --git a/ui/img/emoji/wink.png b/ui/img/emoji/wink.png new file mode 100644 index 0000000..756766d Binary files /dev/null and b/ui/img/emoji/wink.png differ diff --git a/ui/img/emoji/wolf.png b/ui/img/emoji/wolf.png new file mode 100644 index 0000000..c60c968 Binary files /dev/null and b/ui/img/emoji/wolf.png differ diff --git a/ui/img/emoji/woman.png b/ui/img/emoji/woman.png new file mode 100644 index 0000000..6bf0d2b Binary files /dev/null and b/ui/img/emoji/woman.png differ diff --git a/ui/img/emoji/womans_clothes.png b/ui/img/emoji/womans_clothes.png new file mode 100644 index 0000000..aa297c7 Binary files /dev/null and b/ui/img/emoji/womans_clothes.png differ diff --git a/ui/img/emoji/womans_hat.png b/ui/img/emoji/womans_hat.png new file mode 100644 index 0000000..4cb2e6a Binary files /dev/null and b/ui/img/emoji/womans_hat.png differ diff --git a/ui/img/emoji/womens.png b/ui/img/emoji/womens.png new file mode 100644 index 0000000..2fab296 Binary files /dev/null and b/ui/img/emoji/womens.png differ diff --git a/ui/img/emoji/worried.png b/ui/img/emoji/worried.png new file mode 100644 index 0000000..bfa1856 Binary files /dev/null and b/ui/img/emoji/worried.png differ diff --git a/ui/img/emoji/wrench.png b/ui/img/emoji/wrench.png new file mode 100644 index 0000000..a87072a Binary files /dev/null and b/ui/img/emoji/wrench.png differ diff --git a/ui/img/emoji/x.png b/ui/img/emoji/x.png new file mode 100644 index 0000000..dff9efa Binary files /dev/null and b/ui/img/emoji/x.png differ diff --git a/ui/img/emoji/yellow_heart.png b/ui/img/emoji/yellow_heart.png new file mode 100644 index 0000000..fa41ce7 Binary files /dev/null and b/ui/img/emoji/yellow_heart.png differ diff --git a/ui/img/emoji/yen.png b/ui/img/emoji/yen.png new file mode 100644 index 0000000..139bc93 Binary files /dev/null and b/ui/img/emoji/yen.png differ diff --git a/ui/img/emoji/yum.png b/ui/img/emoji/yum.png new file mode 100644 index 0000000..fc39637 Binary files /dev/null and b/ui/img/emoji/yum.png differ diff --git a/ui/img/emoji/zap.png b/ui/img/emoji/zap.png new file mode 100644 index 0000000..260c531 Binary files /dev/null and b/ui/img/emoji/zap.png differ diff --git a/ui/img/emoji/zero.png b/ui/img/emoji/zero.png new file mode 100644 index 0000000..6e57b33 Binary files /dev/null and b/ui/img/emoji/zero.png differ diff --git a/ui/img/emoji/zzz.png b/ui/img/emoji/zzz.png new file mode 100644 index 0000000..30be046 Binary files /dev/null and b/ui/img/emoji/zzz.png differ diff --git a/ui/img/external-link.svg b/ui/img/external-link.svg new file mode 100644 index 0000000..e816105 --- /dev/null +++ b/ui/img/external-link.svg @@ -0,0 +1,25 @@ + + + + + + + diff --git a/ui/img/icon.png b/ui/img/icon.png new file mode 100644 index 0000000..f29ffdc Binary files /dev/null and b/ui/img/icon.png differ diff --git a/ui/img/icon.pxm b/ui/img/icon.pxm new file mode 100644 index 0000000..ca420a9 Binary files /dev/null and b/ui/img/icon.pxm differ diff --git a/ui/img/lick-the-door.gif b/ui/img/lick-the-door.gif new file mode 100644 index 0000000..cdab2f1 Binary files /dev/null and b/ui/img/lick-the-door.gif differ diff --git a/ui/img/lines.svg b/ui/img/lines.svg new file mode 100644 index 0000000..624c724 --- /dev/null +++ b/ui/img/lines.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/ui/img/spinner.gif b/ui/img/spinner.gif new file mode 100644 index 0000000..c7a050e Binary files /dev/null and b/ui/img/spinner.gif differ diff --git a/ui/img/spinner.webm b/ui/img/spinner.webm new file mode 100644 index 0000000..6898481 Binary files /dev/null and b/ui/img/spinner.webm differ diff --git a/ui/less/bootstrap/.csscomb.json b/ui/less/bootstrap/.csscomb.json new file mode 100644 index 0000000..40695a4 --- /dev/null +++ b/ui/less/bootstrap/.csscomb.json @@ -0,0 +1,304 @@ +{ + "always-semicolon": true, + "block-indent": 2, + "color-case": "lower", + "color-shorthand": true, + "element-case": "lower", + "eof-newline": true, + "leading-zero": false, + "remove-empty-rulesets": true, + "space-after-colon": 1, + "space-after-combinator": 1, + "space-before-selector-delimiter": 0, + "space-between-declarations": "\n", + "space-after-opening-brace": "\n", + "space-before-closing-brace": "\n", + "space-before-colon": 0, + "space-before-combinator": 1, + "space-before-opening-brace": 1, + "strip-spaces": true, + "unitless-zero": true, + "vendor-prefix-align": true, + "sort-order": [ + [ + "position", + "top", + "right", + "bottom", + "left", + "z-index", + "display", + "float", + "width", + "min-width", + "max-width", + "height", + "min-height", + "max-height", + "-webkit-box-sizing", + "-moz-box-sizing", + "box-sizing", + "-webkit-appearance", + "padding", + "padding-top", + "padding-right", + "padding-bottom", + "padding-left", + "margin", + "margin-top", + "margin-right", + "margin-bottom", + "margin-left", + "overflow", + "overflow-x", + "overflow-y", + "-webkit-overflow-scrolling", + "-ms-overflow-x", + "-ms-overflow-y", + "-ms-overflow-style", + "clip", + "clear", + "font", + "font-family", + "font-size", + "font-style", + "font-weight", + "font-variant", + "font-size-adjust", + "font-stretch", + "font-effect", + "font-emphasize", + "font-emphasize-position", + "font-emphasize-style", + "font-smooth", + "-webkit-hyphens", + "-moz-hyphens", + "hyphens", + "line-height", + "color", + "text-align", + "-webkit-text-align-last", + "-moz-text-align-last", + "-ms-text-align-last", + "text-align-last", + "text-emphasis", + "text-emphasis-color", + "text-emphasis-style", + "text-emphasis-position", + "text-decoration", + "text-indent", + "text-justify", + "text-outline", + "-ms-text-overflow", + "text-overflow", + "text-overflow-ellipsis", + "text-overflow-mode", + "text-shadow", + "text-transform", + "text-wrap", + "-webkit-text-size-adjust", + "-ms-text-size-adjust", + "letter-spacing", + "-ms-word-break", + "word-break", + "word-spacing", + "-ms-word-wrap", + "word-wrap", + "-moz-tab-size", + "-o-tab-size", + "tab-size", + "white-space", + "vertical-align", + "list-style", + "list-style-position", + "list-style-type", + "list-style-image", + "pointer-events", + "-ms-touch-action", + "touch-action", + "cursor", + "visibility", + "zoom", + "flex-direction", + "flex-order", + "flex-pack", + "flex-align", + "table-layout", + "empty-cells", + "caption-side", + "border-spacing", + "border-collapse", + "content", + "quotes", + "counter-reset", + "counter-increment", + "resize", + "-webkit-user-select", + "-moz-user-select", + "-ms-user-select", + "-o-user-select", + "user-select", + "nav-index", + "nav-up", + "nav-right", + "nav-down", + "nav-left", + "background", + "background-color", + "background-image", + "-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient", + "filter:progid:DXImageTransform.Microsoft.gradient", + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader", + "filter", + "background-repeat", + "background-attachment", + "background-position", + "background-position-x", + "background-position-y", + "-webkit-background-clip", + "-moz-background-clip", + "background-clip", + "background-origin", + "-webkit-background-size", + "-moz-background-size", + "-o-background-size", + "background-size", + "border", + "border-color", + "border-style", + "border-width", + "border-top", + "border-top-color", + "border-top-style", + "border-top-width", + "border-right", + "border-right-color", + "border-right-style", + "border-right-width", + "border-bottom", + "border-bottom-color", + "border-bottom-style", + "border-bottom-width", + "border-left", + "border-left-color", + "border-left-style", + "border-left-width", + "border-radius", + "border-top-left-radius", + "border-top-right-radius", + "border-bottom-right-radius", + "border-bottom-left-radius", + "-webkit-border-image", + "-moz-border-image", + "-o-border-image", + "border-image", + "-webkit-border-image-source", + "-moz-border-image-source", + "-o-border-image-source", + "border-image-source", + "-webkit-border-image-slice", + "-moz-border-image-slice", + "-o-border-image-slice", + "border-image-slice", + "-webkit-border-image-width", + "-moz-border-image-width", + "-o-border-image-width", + "border-image-width", + "-webkit-border-image-outset", + "-moz-border-image-outset", + "-o-border-image-outset", + "border-image-outset", + "-webkit-border-image-repeat", + "-moz-border-image-repeat", + "-o-border-image-repeat", + "border-image-repeat", + "outline", + "outline-width", + "outline-style", + "outline-color", + "outline-offset", + "-webkit-box-shadow", + "-moz-box-shadow", + "box-shadow", + "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity", + "-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha", + "opacity", + "-ms-interpolation-mode", + "-webkit-transition", + "-moz-transition", + "-ms-transition", + "-o-transition", + "transition", + "-webkit-transition-delay", + "-moz-transition-delay", + "-ms-transition-delay", + "-o-transition-delay", + "transition-delay", + "-webkit-transition-timing-function", + "-moz-transition-timing-function", + "-ms-transition-timing-function", + "-o-transition-timing-function", + "transition-timing-function", + "-webkit-transition-duration", + "-moz-transition-duration", + "-ms-transition-duration", + "-o-transition-duration", + "transition-duration", + "-webkit-transition-property", + "-moz-transition-property", + "-ms-transition-property", + "-o-transition-property", + "transition-property", + "-webkit-transform", + "-moz-transform", + "-ms-transform", + "-o-transform", + "transform", + "-webkit-transform-origin", + "-moz-transform-origin", + "-ms-transform-origin", + "-o-transform-origin", + "transform-origin", + "-webkit-animation", + "-moz-animation", + "-ms-animation", + "-o-animation", + "animation", + "-webkit-animation-name", + "-moz-animation-name", + "-ms-animation-name", + "-o-animation-name", + "animation-name", + "-webkit-animation-duration", + "-moz-animation-duration", + "-ms-animation-duration", + "-o-animation-duration", + "animation-duration", + "-webkit-animation-play-state", + "-moz-animation-play-state", + "-ms-animation-play-state", + "-o-animation-play-state", + "animation-play-state", + "-webkit-animation-timing-function", + "-moz-animation-timing-function", + "-ms-animation-timing-function", + "-o-animation-timing-function", + "animation-timing-function", + "-webkit-animation-delay", + "-moz-animation-delay", + "-ms-animation-delay", + "-o-animation-delay", + "animation-delay", + "-webkit-animation-iteration-count", + "-moz-animation-iteration-count", + "-ms-animation-iteration-count", + "-o-animation-iteration-count", + "animation-iteration-count", + "-webkit-animation-direction", + "-moz-animation-direction", + "-ms-animation-direction", + "-o-animation-direction", + "animation-direction" + ] + ] +} diff --git a/ui/less/bootstrap/.csslintrc b/ui/less/bootstrap/.csslintrc new file mode 100644 index 0000000..005b862 --- /dev/null +++ b/ui/less/bootstrap/.csslintrc @@ -0,0 +1,19 @@ +{ + "adjoining-classes": false, + "box-sizing": false, + "box-model": false, + "compatible-vendor-prefixes": false, + "floats": false, + "font-sizes": false, + "gradients": false, + "important": false, + "known-properties": false, + "outline-none": false, + "qualified-headings": false, + "regex-selectors": false, + "shorthand": false, + "text-indent": false, + "unique-headings": false, + "universal-selector": false, + "unqualified-attributes": false +} diff --git a/ui/less/bootstrap/alerts.less b/ui/less/bootstrap/alerts.less new file mode 100644 index 0000000..df070b8 --- /dev/null +++ b/ui/less/bootstrap/alerts.less @@ -0,0 +1,68 @@ +// +// Alerts +// -------------------------------------------------- + + +// Base styles +// ------------------------- + +.alert { + padding: @alert-padding; + margin-bottom: @line-height-computed; + border: 1px solid transparent; + border-radius: @alert-border-radius; + + // Headings for larger alerts + h4 { + margin-top: 0; + // Specified for the h4 to prevent conflicts of changing @headings-color + color: inherit; + } + // Provide class for links that match alerts + .alert-link { + font-weight: @alert-link-font-weight; + } + + // Improve alignment and spacing of inner content + > p, + > ul { + margin-bottom: 0; + } + > p + p { + margin-top: 5px; + } +} + +// Dismissible alerts +// +// Expand the right padding and account for the close button's positioning. + +.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0. +.alert-dismissible { + padding-right: (@alert-padding + 20); + + // Adjust close link position + .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; + } +} + +// Alternate styles +// +// Generate contextual modifier classes for colorizing the alert. + +.alert-success { + .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text); +} +.alert-info { + .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text); +} +.alert-warning { + .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text); +} +.alert-danger { + .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text); +} diff --git a/ui/less/bootstrap/badges.less b/ui/less/bootstrap/badges.less new file mode 100644 index 0000000..20624f3 --- /dev/null +++ b/ui/less/bootstrap/badges.less @@ -0,0 +1,55 @@ +// +// Badges +// -------------------------------------------------- + + +// Base class +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: @font-size-small; + font-weight: @badge-font-weight; + color: @badge-color; + line-height: @badge-line-height; + vertical-align: baseline; + white-space: nowrap; + text-align: center; + background-color: @badge-bg; + border-radius: @badge-border-radius; + + // Empty badges collapse automatically (not available in IE8) + &:empty { + display: none; + } + + // Quick fix for badges in buttons + .btn & { + position: relative; + top: -1px; + } + .btn-xs & { + top: 0; + padding: 1px 5px; + } + + // Hover state, but only for links + a& { + &:hover, + &:focus { + color: @badge-link-hover-color; + text-decoration: none; + cursor: pointer; + } + } + + // Account for badges in navs + a.list-group-item.active > &, + .nav-pills > .active > a > & { + color: @badge-active-color; + background-color: @badge-active-bg; + } + .nav-pills > li > a > & { + margin-left: 3px; + } +} diff --git a/ui/less/bootstrap/bootstrap.less b/ui/less/bootstrap/bootstrap.less new file mode 100644 index 0000000..61b7747 --- /dev/null +++ b/ui/less/bootstrap/bootstrap.less @@ -0,0 +1,50 @@ +// Core variables and mixins +@import "variables.less"; +@import "mixins.less"; + +// Reset and dependencies +@import "normalize.less"; +@import "print.less"; +@import "glyphicons.less"; + +// Core CSS +@import "scaffolding.less"; +@import "type.less"; +@import "code.less"; +@import "grid.less"; +@import "tables.less"; +@import "forms.less"; +@import "buttons.less"; + +// Components +@import "component-animations.less"; +@import "dropdowns.less"; +@import "button-groups.less"; +@import "input-groups.less"; +@import "navs.less"; +@import "navbar.less"; +@import "breadcrumbs.less"; +@import "pagination.less"; +@import "pager.less"; +@import "labels.less"; +@import "badges.less"; +@import "jumbotron.less"; +@import "thumbnails.less"; +@import "alerts.less"; +@import "progress-bars.less"; +@import "media.less"; +@import "list-group.less"; +@import "panels.less"; +@import "responsive-embed.less"; +@import "wells.less"; +@import "close.less"; + +// Components w/ JavaScript +@import "modals.less"; +@import "tooltip.less"; +@import "popovers.less"; +@import "carousel.less"; + +// Utility classes +@import "utilities.less"; +@import "responsive-utilities.less"; diff --git a/ui/less/bootstrap/breadcrumbs.less b/ui/less/bootstrap/breadcrumbs.less new file mode 100644 index 0000000..cb01d50 --- /dev/null +++ b/ui/less/bootstrap/breadcrumbs.less @@ -0,0 +1,26 @@ +// +// Breadcrumbs +// -------------------------------------------------- + + +.breadcrumb { + padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal; + margin-bottom: @line-height-computed; + list-style: none; + background-color: @breadcrumb-bg; + border-radius: @border-radius-base; + + > li { + display: inline-block; + + + li:before { + content: "@{breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space + padding: 0 5px; + color: @breadcrumb-color; + } + } + + > .active { + color: @breadcrumb-active-color; + } +} diff --git a/ui/less/bootstrap/button-groups.less b/ui/less/bootstrap/button-groups.less new file mode 100644 index 0000000..fbcdf45 --- /dev/null +++ b/ui/less/bootstrap/button-groups.less @@ -0,0 +1,247 @@ +// +// Button groups +// -------------------------------------------------- + +// Make the div behave like a button +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; // match .btn alignment given font-size hack above + > .btn { + position: relative; + float: left; + // Bring the "active" button to the front + &:hover, + &:focus, + &:active, + &.active { + z-index: 2; + } + &:focus { + // Remove focus outline when dropdown JS adds it after closing the menu + outline: 0; + } + } +} + +// Prevent double borders when buttons are next to each other +.btn-group { + .btn + .btn, + .btn + .btn-group, + .btn-group + .btn, + .btn-group + .btn-group { + margin-left: -1px; + } +} + +// Optional: Group multiple button groups together for a toolbar +.btn-toolbar { + margin-left: -5px; // Offset the first child's margin + &:extend(.clearfix all); + + .btn-group, + .input-group { + float: left; + } + > .btn, + > .btn-group, + > .input-group { + margin-left: 5px; + } +} + +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} + +// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match +.btn-group > .btn:first-child { + margin-left: 0; + &:not(:last-child):not(.dropdown-toggle) { + .border-right-radius(0); + } +} +// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + .border-left-radius(0); +} + +// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group) +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child { + > .btn:last-child, + > .dropdown-toggle { + .border-right-radius(0); + } +} +.btn-group > .btn-group:last-child > .btn:first-child { + .border-left-radius(0); +} + +// On active and open, don't show outline +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + + +// Sizing +// +// Remix the default button sizing classes into new ones for easier manipulation. + +.btn-group-xs > .btn { &:extend(.btn-xs); } +.btn-group-sm > .btn { &:extend(.btn-sm); } +.btn-group-lg > .btn { &:extend(.btn-lg); } + + +// Split button dropdowns +// ---------------------- + +// Give the line between buttons some depth +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} + +// The clickable button for toggling the menu +// Remove the gradient and set the same inset shadow as the :active state +.btn-group.open .dropdown-toggle { + .box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); + + // Show no shadow for `.btn-link` since it has no other button styles. + &.btn-link { + .box-shadow(none); + } +} + + +// Reposition the caret +.btn .caret { + margin-left: 0; +} +// Carets in other button sizes +.btn-lg .caret { + border-width: @caret-width-large @caret-width-large 0; + border-bottom-width: 0; +} +// Upside down carets for .dropup +.dropup .btn-lg .caret { + border-width: 0 @caret-width-large @caret-width-large; +} + + +// Vertical button groups +// ---------------------- + +.btn-group-vertical { + > .btn, + > .btn-group, + > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; + } + + // Clear floats so dropdown menus can be properly placed + > .btn-group { + &:extend(.clearfix all); + > .btn { + float: none; + } + } + + > .btn + .btn, + > .btn + .btn-group, + > .btn-group + .btn, + > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; + } +} + +.btn-group-vertical > .btn { + &:not(:first-child):not(:last-child) { + border-radius: 0; + } + &:first-child:not(:last-child) { + border-top-right-radius: @border-radius-base; + .border-bottom-radius(0); + } + &:last-child:not(:first-child) { + border-bottom-left-radius: @border-radius-base; + .border-top-radius(0); + } +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) { + > .btn:last-child, + > .dropdown-toggle { + .border-bottom-radius(0); + } +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + .border-top-radius(0); +} + + +// Justified button groups +// ---------------------- + +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; + > .btn, + > .btn-group { + float: none; + display: table-cell; + width: 1%; + } + > .btn-group .btn { + width: 100%; + } + + > .btn-group .dropdown-menu { + left: auto; + } +} + + +// Checkbox and radio options +// +// In order to support the browser's form validation feedback, powered by the +// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use +// `display: none;` or `visibility: hidden;` as that also hides the popover. +// Simply visually hiding the inputs via `opacity` would leave them clickable in +// certain cases which is prevented by using `clip` and `pointer-events`. +// This way, we ensure a DOM element is visible to position the popover from. +// +// See https://github.com/twbs/bootstrap/pull/12794 and +// https://github.com/twbs/bootstrap/pull/14559 for more information. + +[data-toggle="buttons"] { + > .btn, + > .btn-group > .btn { + input[type="radio"], + input[type="checkbox"] { + position: absolute; + clip: rect(0,0,0,0); + pointer-events: none; + } + } +} diff --git a/ui/less/bootstrap/buttons.less b/ui/less/bootstrap/buttons.less new file mode 100644 index 0000000..40553c6 --- /dev/null +++ b/ui/less/bootstrap/buttons.less @@ -0,0 +1,160 @@ +// +// Buttons +// -------------------------------------------------- + + +// Base styles +// -------------------------------------------------- + +.btn { + display: inline-block; + margin-bottom: 0; // For input.btn + font-weight: @btn-font-weight; + text-align: center; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 + border: 1px solid transparent; + white-space: nowrap; + .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base); + .user-select(none); + + &, + &:active, + &.active { + &:focus, + &.focus { + .tab-focus(); + } + } + + &:hover, + &:focus, + &.focus { + color: @btn-default-color; + text-decoration: none; + } + + &:active, + &.active { + outline: 0; + background-image: none; + .box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); + } + + &.disabled, + &[disabled], + fieldset[disabled] & { + cursor: @cursor-disabled; + pointer-events: none; // Future-proof disabling of clicks + .opacity(.65); + .box-shadow(none); + } +} + + +// Alternate buttons +// -------------------------------------------------- + +.btn-default { + .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border); +} +.btn-primary { + .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border); +} +// Success appears as green +.btn-success { + .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border); +} +// Info appears as blue-green +.btn-info { + .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border); +} +// Warning appears as orange +.btn-warning { + .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border); +} +// Danger and error appear as red +.btn-danger { + .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border); +} + + +// Link buttons +// ------------------------- + +// Make a button look and behave like a link +.btn-link { + color: @link-color; + font-weight: normal; + border-radius: 0; + + &, + &:active, + &.active, + &[disabled], + fieldset[disabled] & { + background-color: transparent; + .box-shadow(none); + } + &, + &:hover, + &:focus, + &:active { + border-color: transparent; + } + &:hover, + &:focus { + color: @link-hover-color; + text-decoration: underline; + background-color: transparent; + } + &[disabled], + fieldset[disabled] & { + &:hover, + &:focus { + color: @btn-link-disabled-color; + text-decoration: none; + } + } +} + + +// Button Sizes +// -------------------------------------------------- + +.btn-lg { + // line-height: ensure even-numbered height of button next to large input + .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large); +} +.btn-sm { + // line-height: ensure proper height of button next to small input + .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small); +} +.btn-xs { + .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small); +} + + +// Block button +// -------------------------------------------------- + +.btn-block { + display: block; + width: 100%; +} + +// Vertically space out multiple block buttons +.btn-block + .btn-block { + margin-top: 5px; +} + +// Specificity overrides +input[type="submit"], +input[type="reset"], +input[type="button"] { + &.btn-block { + width: 100%; + } +} diff --git a/ui/less/bootstrap/carousel.less b/ui/less/bootstrap/carousel.less new file mode 100644 index 0000000..5724d8a --- /dev/null +++ b/ui/less/bootstrap/carousel.less @@ -0,0 +1,267 @@ +// +// Carousel +// -------------------------------------------------- + + +// Wrapper for the slide container and indicators +.carousel { + position: relative; +} + +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; + + > .item { + display: none; + position: relative; + .transition(.6s ease-in-out left); + + // Account for jankitude on images + > img, + > a > img { + &:extend(.img-responsive); + line-height: 1; + } + + // WebKit CSS3 transforms for supported devices + @media all and (transform-3d), (-webkit-transform-3d) { + transition: transform .6s ease-in-out; + backface-visibility: hidden; + perspective: 1000; + + &.next, + &.active.right { + transform: translate3d(100%, 0, 0); + left: 0; + } + &.prev, + &.active.left { + transform: translate3d(-100%, 0, 0); + left: 0; + } + &.next.left, + &.prev.right, + &.active { + transform: translate3d(0, 0, 0); + left: 0; + } + } + } + + > .active, + > .next, + > .prev { + display: block; + } + + > .active { + left: 0; + } + + > .next, + > .prev { + position: absolute; + top: 0; + width: 100%; + } + + > .next { + left: 100%; + } + > .prev { + left: -100%; + } + > .next.left, + > .prev.right { + left: 0; + } + + > .active.left { + left: -100%; + } + > .active.right { + left: 100%; + } + +} + +// Left/right controls for nav +// --------------------------- + +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: @carousel-control-width; + .opacity(@carousel-control-opacity); + font-size: @carousel-control-font-size; + color: @carousel-control-color; + text-align: center; + text-shadow: @carousel-text-shadow; + // We can't have this transition here because WebKit cancels the carousel + // animation if you trip this while in the middle of another animation. + + // Set gradients for backgrounds + &.left { + #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001)); + } + &.right { + left: auto; + right: 0; + #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5)); + } + + // Hover/focus state + &:hover, + &:focus { + outline: 0; + color: @carousel-control-color; + text-decoration: none; + .opacity(.9); + } + + // Toggles + .icon-prev, + .icon-next, + .glyphicon-chevron-left, + .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; + } + .icon-prev, + .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; + } + .icon-next, + .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; + } + .icon-prev, + .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + font-family: serif; + } + + + .icon-prev { + &:before { + content: '\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039) + } + } + .icon-next { + &:before { + content: '\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A) + } + } +} + +// Optional indicator pips +// +// Add an unordered list with the following class and add a list item for each +// slide your carousel holds. + +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; + + li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid @carousel-indicator-border-color; + border-radius: 10px; + cursor: pointer; + + // IE8-9 hack for event handling + // + // Internet Explorer 8-9 does not support clicks on elements without a set + // `background-color`. We cannot use `filter` since that's not viewed as a + // background color by the browser. Thus, a hack is needed. + // + // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we + // set alpha transparency for the best results possible. + background-color: #000 \9; // IE8 + background-color: rgba(0,0,0,0); // IE9 + } + .active { + margin: 0; + width: 12px; + height: 12px; + background-color: @carousel-indicator-active-bg; + } +} + +// Optional captions +// ----------------------------- +// Hidden by default for smaller viewports +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: @carousel-caption-color; + text-align: center; + text-shadow: @carousel-text-shadow; + & .btn { + text-shadow: none; // No shadow for button elements in carousel-caption + } +} + + +// Scale up controls for tablets and up +@media screen and (min-width: @screen-sm-min) { + + // Scale up the controls a smidge + .carousel-control { + .glyphicon-chevron-left, + .glyphicon-chevron-right, + .icon-prev, + .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + .glyphicon-chevron-left, + .icon-prev { + margin-left: -15px; + } + .glyphicon-chevron-right, + .icon-next { + margin-right: -15px; + } + } + + // Show and left align the captions + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + + // Move up the indicators + .carousel-indicators { + bottom: 20px; + } +} diff --git a/ui/less/bootstrap/close.less b/ui/less/bootstrap/close.less new file mode 100644 index 0000000..9b4e74f --- /dev/null +++ b/ui/less/bootstrap/close.less @@ -0,0 +1,33 @@ +// +// Close icons +// -------------------------------------------------- + + +.close { + float: right; + font-size: (@font-size-base * 1.5); + font-weight: @close-font-weight; + line-height: 1; + color: @close-color; + text-shadow: @close-text-shadow; + .opacity(.2); + + &:hover, + &:focus { + color: @close-color; + text-decoration: none; + cursor: pointer; + .opacity(.5); + } + + // Additional properties for button version + // iOS requires the button element instead of an anchor tag. + // If you want the anchor version, it requires `href="#"`. + button& { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; + } +} diff --git a/ui/less/bootstrap/code.less b/ui/less/bootstrap/code.less new file mode 100644 index 0000000..a08b4d4 --- /dev/null +++ b/ui/less/bootstrap/code.less @@ -0,0 +1,69 @@ +// +// Code (inline and block) +// -------------------------------------------------- + + +// Inline and block code styles +code, +kbd, +pre, +samp { + font-family: @font-family-monospace; +} + +// Inline code +code { + padding: 2px 4px; + font-size: 90%; + color: @code-color; + background-color: @code-bg; + border-radius: @border-radius-base; +} + +// User input typically entered via keyboard +kbd { + padding: 2px 4px; + font-size: 90%; + color: @kbd-color; + background-color: @kbd-bg; + border-radius: @border-radius-small; + box-shadow: inset 0 -1px 0 rgba(0,0,0,.25); + + kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + box-shadow: none; + } +} + +// Blocks of code +pre { + display: block; + padding: ((@line-height-computed - 1) / 2); + margin: 0 0 (@line-height-computed / 2); + font-size: (@font-size-base - 1); // 14px to 13px + line-height: @line-height-base; + word-break: break-all; + word-wrap: break-word; + color: @pre-color; + background-color: @pre-bg; + border: 1px solid @pre-border-color; + border-radius: @border-radius-base; + + // Account for some code outputs that place code tags in pre tags + code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; + } +} + +// Enable scrollable blocks of code +.pre-scrollable { + max-height: @pre-scrollable-max-height; + overflow-y: scroll; +} diff --git a/ui/less/bootstrap/component-animations.less b/ui/less/bootstrap/component-animations.less new file mode 100644 index 0000000..967715d --- /dev/null +++ b/ui/less/bootstrap/component-animations.less @@ -0,0 +1,34 @@ +// +// Component animations +// -------------------------------------------------- + +// Heads up! +// +// We don't use the `.opacity()` mixin here since it causes a bug with text +// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552. + +.fade { + opacity: 0; + .transition(opacity .15s linear); + &.in { + opacity: 1; + } +} + +.collapse { + display: none; + visibility: hidden; + + &.in { display: block; visibility: visible; } + tr&.in { display: table-row; } + tbody&.in { display: table-row-group; } +} + +.collapsing { + position: relative; + height: 0; + overflow: hidden; + .transition-property(~"height, visibility"); + .transition-duration(.35s); + .transition-timing-function(ease); +} diff --git a/ui/less/bootstrap/dropdowns.less b/ui/less/bootstrap/dropdowns.less new file mode 100644 index 0000000..84a48c1 --- /dev/null +++ b/ui/less/bootstrap/dropdowns.less @@ -0,0 +1,213 @@ +// +// Dropdown menus +// -------------------------------------------------- + + +// Dropdown arrow/caret +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: @caret-width-base solid; + border-right: @caret-width-base solid transparent; + border-left: @caret-width-base solid transparent; +} + +// The dropdown wrapper (div) +.dropdown { + position: relative; +} + +// Prevent the focus on the dropdown toggle when closing dropdowns +.dropdown-toggle:focus { + outline: 0; +} + +// The dropdown menu (ul) +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: @zindex-dropdown; + display: none; // none by default, but block on "open" of the menu + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; // override default ul + list-style: none; + font-size: @font-size-base; + text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer) + background-color: @dropdown-bg; + border: 1px solid @dropdown-fallback-border; // IE8 fallback + border: 1px solid @dropdown-border; + border-radius: @border-radius-base; + .box-shadow(0 6px 12px rgba(0,0,0,.175)); + background-clip: padding-box; + + // Aligns the dropdown menu to right + // + // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]` + &.pull-right { + right: 0; + left: auto; + } + + // Dividers (basically an hr) within the dropdown + .divider { + .nav-divider(@dropdown-divider-bg); + } + + // Links within the dropdown menu + > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: @line-height-base; + color: @dropdown-link-color; + white-space: nowrap; // prevent links from randomly breaking onto new lines + } +} + +// Hover/Focus state +.dropdown-menu > li > a { + &:hover, + &:focus { + text-decoration: none; + color: @dropdown-link-hover-color; + background-color: @dropdown-link-hover-bg; + } +} + +// Active state +.dropdown-menu > .active > a { + &, + &:hover, + &:focus { + color: @dropdown-link-active-color; + text-decoration: none; + outline: 0; + background-color: @dropdown-link-active-bg; + } +} + +// Disabled state +// +// Gray out text and ensure the hover/focus state remains gray + +.dropdown-menu > .disabled > a { + &, + &:hover, + &:focus { + color: @dropdown-link-disabled-color; + } + + // Nuke hover/focus effects + &:hover, + &:focus { + text-decoration: none; + background-color: transparent; + background-image: none; // Remove CSS gradient + .reset-filter(); + cursor: @cursor-disabled; + } +} + +// Open state for the dropdown +.open { + // Show the menu + > .dropdown-menu { + display: block; + } + + // Remove the outline when :focus is triggered + > a { + outline: 0; + } +} + +// Menu positioning +// +// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown +// menu with the parent. +.dropdown-menu-right { + left: auto; // Reset the default from `.dropdown-menu` + right: 0; +} +// With v3, we enabled auto-flipping if you have a dropdown within a right +// aligned nav component. To enable the undoing of that, we provide an override +// to restore the default dropdown menu alignment. +// +// This is only for left-aligning a dropdown menu within a `.navbar-right` or +// `.pull-right` nav component. +.dropdown-menu-left { + left: 0; + right: auto; +} + +// Dropdown section headers +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: @font-size-small; + line-height: @line-height-base; + color: @dropdown-header-color; + white-space: nowrap; // as with > li > a +} + +// Backdrop to catch body clicks on mobile, etc. +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: (@zindex-dropdown - 10); +} + +// Right aligned dropdowns +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +// Allow for dropdowns to go bottom up (aka, dropup-menu) +// +// Just add .dropup after the standard .dropdown class and you're set, bro. +// TODO: abstract this so that the navbar fixed styles are not placed here? + +.dropup, +.navbar-fixed-bottom .dropdown { + // Reverse the caret + .caret { + border-top: 0; + border-bottom: @caret-width-base solid; + content: ""; + } + // Different positioning for bottom up menu + .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; + } +} + + +// Component alignment +// +// Reiterate per navbar.less and the modified component alignment there. + +@media (min-width: @grid-float-breakpoint) { + .navbar-right { + .dropdown-menu { + .dropdown-menu-right(); + } + // Necessary for overrides of the default right aligned menu. + // Will remove come v4 in all likelihood. + .dropdown-menu-left { + .dropdown-menu-left(); + } + } +} diff --git a/ui/less/bootstrap/forms.less b/ui/less/bootstrap/forms.less new file mode 100644 index 0000000..38e4ce6 --- /dev/null +++ b/ui/less/bootstrap/forms.less @@ -0,0 +1,559 @@ +// +// Forms +// -------------------------------------------------- + + +// Normalize non-controls +// +// Restyle and baseline non-control form elements. + +fieldset { + padding: 0; + margin: 0; + border: 0; + // Chrome and Firefox set a `min-width: min-content;` on fieldsets, + // so we reset that to ensure it behaves more like a standard block element. + // See https://github.com/twbs/bootstrap/issues/12359. + min-width: 0; +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: @line-height-computed; + font-size: (@font-size-base * 1.5); + line-height: inherit; + color: @legend-color; + border: 0; + border-bottom: 1px solid @legend-border-color; +} + +label { + display: inline-block; + max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141) + margin-bottom: 5px; + font-weight: bold; +} + + +// Normalize form controls +// +// While most of our form styles require extra classes, some basic normalization +// is required to ensure optimum display with or without those classes to better +// address browser inconsistencies. + +// Override content-box in Normalize (* isn't specific enough) +input[type="search"] { + .box-sizing(border-box); +} + +// Position radios and checkboxes better +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; // IE8-9 + line-height: normal; +} + +// Set the height of file controls to match text inputs +input[type="file"] { + display: block; +} + +// Make range inputs behave like textual form controls +input[type="range"] { + display: block; + width: 100%; +} + +// Make multiple select elements height not fixed +select[multiple], +select[size] { + height: auto; +} + +// Focus for file, radio, and checkbox +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + .tab-focus(); +} + +// Adjust output element +output { + display: block; + padding-top: (@padding-base-vertical + 1); + font-size: @font-size-base; + line-height: @line-height-base; + color: @input-color; +} + + +// Common form controls +// +// Shared size and type resets for form controls. Apply `.form-control` to any +// of the following form controls: +// +// select +// textarea +// input[type="text"] +// input[type="password"] +// input[type="datetime"] +// input[type="datetime-local"] +// input[type="date"] +// input[type="month"] +// input[type="time"] +// input[type="week"] +// input[type="number"] +// input[type="email"] +// input[type="url"] +// input[type="search"] +// input[type="tel"] +// input[type="color"] + +.form-control { + display: block; + width: 100%; + height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border) + padding: @padding-base-vertical @padding-base-horizontal; + font-size: @font-size-base; + line-height: @line-height-base; + color: @input-color; + background-color: @input-bg; + background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 + border: 1px solid @input-border; + border-radius: @input-border-radius; + .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); + .transition(~"border-color ease-in-out .15s, box-shadow ease-in-out .15s"); + + // Customize the `:focus` state to imitate native WebKit styles. + .form-control-focus(); + + // Placeholder + .placeholder(); + + // Disabled and read-only inputs + // + // HTML5 says that controls under a fieldset > legend:first-child won't be + // disabled if the fieldset is disabled. Due to implementation difficulty, we + // don't honor that edge case; we style them as disabled anyway. + &[disabled], + &[readonly], + fieldset[disabled] & { + cursor: @cursor-disabled; + background-color: @input-bg-disabled; + opacity: 1; // iOS fix for unreadable disabled content + } + + // Reset height for `textarea`s + textarea& { + height: auto; + } +} + + +// Search inputs in iOS +// +// This overrides the extra rounded corners on search inputs in iOS so that our +// `.form-control` class can properly style them. Note that this cannot simply +// be added to `.form-control` as it's not specific enough. For details, see +// https://github.com/twbs/bootstrap/issues/11586. + +input[type="search"] { + -webkit-appearance: none; +} + + +// Special styles for iOS temporal inputs +// +// In Mobile Safari, setting `display: block` on temporal inputs causes the +// text within the input to become vertically misaligned. +// As a workaround, we set a pixel line-height that matches the +// given height of the input. Since this fucks up everything else, we have to +// appropriately reset it for Internet Explorer and the size variations. + +input[type="date"], +input[type="time"], +input[type="datetime-local"], +input[type="month"] { + line-height: @input-height-base; + // IE8+ misaligns the text within date inputs, so we reset + line-height: @line-height-base ~"\0"; + + &.input-sm { + line-height: @input-height-small; + line-height: @line-height-small ~"\0"; + } + &.input-lg { + line-height: @input-height-large; + line-height: @line-height-large ~"\0"; + } +} + +// IE 11 hack to reverse the iOS temporal input hack. +_:-ms-fullscreen, :root input[type="date"], +_:-ms-fullscreen, :root input[type="time"], +_:-ms-fullscreen, :root input[type="datetime-local"], +_:-ms-fullscreen, :root input[type="month"] { + line-height: @line-height-base; + + &.input-sm { + line-height: @line-height-small; + } + &.input-lg { + line-height: @line-height-large; + } +} + + +// Form groups +// +// Designed to help with the organization and spacing of vertical forms. For +// horizontal forms, use the predefined grid classes. + +.form-group { + margin-bottom: 15px; +} + + +// Checkboxes and radios +// +// Indent the labels to position radios/checkboxes as hanging controls. + +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; + + label { + min-height: @line-height-computed; // Ensure the input doesn't jump when there is no text + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; + } +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; +} + +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing +} + +// Radios and checkboxes on same line +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; // space out consecutive inline controls +} + +// Apply same disabled cursor tweak as for inputs +// Some special care is needed because