inital emoji support
This commit is contained in:
parent
d2294d9ac7
commit
8b3fe48a74
12 changed files with 377 additions and 7 deletions
|
@ -8,6 +8,8 @@ import { Settings, RoleList } from "./settings.js";
|
||||||
import { Role } from "./role.js";
|
import { Role } from "./role.js";
|
||||||
import { InfiniteScroller } from "./infiniteScroller.js";
|
import { InfiniteScroller } from "./infiniteScroller.js";
|
||||||
import { SnowFlake } from "./snowflake.js";
|
import { SnowFlake } from "./snowflake.js";
|
||||||
|
import { Emoji } from "./emoji.js";
|
||||||
|
new Emoji();
|
||||||
class Channel {
|
class Channel {
|
||||||
editing;
|
editing;
|
||||||
type;
|
type;
|
||||||
|
|
67
.dist/emoji.js
Normal file
67
.dist/emoji.js
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
class Emoji {
|
||||||
|
static emojis;
|
||||||
|
static decodeEmojiList(buffer) {
|
||||||
|
const view = new DataView(buffer, 0);
|
||||||
|
let i = 0;
|
||||||
|
function read16() {
|
||||||
|
const int = view.getUint16(i);
|
||||||
|
i += 2;
|
||||||
|
return int;
|
||||||
|
}
|
||||||
|
function read8() {
|
||||||
|
const int = view.getUint8(i);
|
||||||
|
i += 1;
|
||||||
|
return int;
|
||||||
|
}
|
||||||
|
function readString8() {
|
||||||
|
return readStringNo(read8());
|
||||||
|
}
|
||||||
|
function readString16() {
|
||||||
|
return readStringNo(read16());
|
||||||
|
}
|
||||||
|
function readStringNo(length) {
|
||||||
|
const array = new Uint8Array(length);
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
array[i] = read8();
|
||||||
|
}
|
||||||
|
const decoded = new TextDecoder("utf-8").decode(array.buffer);
|
||||||
|
;
|
||||||
|
//console.log(array);
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
const build = [];
|
||||||
|
let cats = read16();
|
||||||
|
for (; cats !== 0; cats--) {
|
||||||
|
const name = readString16();
|
||||||
|
const emojis = [];
|
||||||
|
let emojinumber = read16();
|
||||||
|
for (; emojinumber !== 0; emojinumber--) {
|
||||||
|
//console.log(emojis);
|
||||||
|
const name = readString8();
|
||||||
|
const len = read8();
|
||||||
|
const skin_tone_support = len > 127;
|
||||||
|
const emoji = readStringNo(len - (+skin_tone_support * 128));
|
||||||
|
emojis.push({
|
||||||
|
name,
|
||||||
|
skin_tone_support,
|
||||||
|
emoji
|
||||||
|
});
|
||||||
|
}
|
||||||
|
build.push({
|
||||||
|
name,
|
||||||
|
emojis
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.emojis = build;
|
||||||
|
console.log(build);
|
||||||
|
}
|
||||||
|
static grabEmoji() {
|
||||||
|
fetch("/emoji.bin").then(e => {
|
||||||
|
return e.arrayBuffer();
|
||||||
|
}).then(e => {
|
||||||
|
Emoji.decodeEmojiList(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Emoji.grabEmoji();
|
||||||
|
export { Emoji };
|
|
@ -363,7 +363,7 @@ class Localuser {
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
div.classList.add("home", "servericon");
|
div.classList.add("home", "servericon");
|
||||||
img.src = "/icons/home.svg";
|
img.src = "/icons/home.svg";
|
||||||
img.classList.add("svgtheme");
|
img.classList.add("svgtheme", "svgicon");
|
||||||
img["all"] = this.guildids.get("@me");
|
img["all"] = this.guildids.get("@me");
|
||||||
this.guildids.get("@me").html = outdiv;
|
this.guildids.get("@me").html = outdiv;
|
||||||
const unread = document.createElement("div");
|
const unread = document.createElement("div");
|
||||||
|
@ -407,7 +407,7 @@ class Localuser {
|
||||||
const guilddsdiv = document.createElement("div");
|
const guilddsdiv = document.createElement("div");
|
||||||
const guildDiscoveryContainer = document.createElement("img");
|
const guildDiscoveryContainer = document.createElement("img");
|
||||||
guildDiscoveryContainer.src = "/icons/explore.svg";
|
guildDiscoveryContainer.src = "/icons/explore.svg";
|
||||||
guildDiscoveryContainer.classList.add("svgtheme");
|
guildDiscoveryContainer.classList.add("svgtheme", "svgicon");
|
||||||
guilddsdiv.classList.add("home", "servericon");
|
guilddsdiv.classList.add("home", "servericon");
|
||||||
guilddsdiv.appendChild(guildDiscoveryContainer);
|
guilddsdiv.appendChild(guildDiscoveryContainer);
|
||||||
serverlist.appendChild(guilddsdiv);
|
serverlist.appendChild(guilddsdiv);
|
||||||
|
@ -922,5 +922,57 @@ class Localuser {
|
||||||
]);
|
]);
|
||||||
botDialog.show();
|
botDialog.show();
|
||||||
}
|
}
|
||||||
|
//---------- resolving members code -----------
|
||||||
|
waitingmembers = new Map();
|
||||||
|
async resolvemember(id, guildid) {
|
||||||
|
console.warn("this function is currently non-functional, either due to a bug in the client or the server, it's currently unclear, use at your own risk");
|
||||||
|
if (!this.waitingmembers.has(guildid)) {
|
||||||
|
this.waitingmembers.set(guildid, new Map());
|
||||||
|
}
|
||||||
|
let res;
|
||||||
|
const promise = new Promise((r) => {
|
||||||
|
res = r;
|
||||||
|
});
|
||||||
|
this.waitingmembers.get(guildid).set(id, res);
|
||||||
|
this.getmembers();
|
||||||
|
return await promise;
|
||||||
|
}
|
||||||
|
fetchingmembers = new Map();
|
||||||
|
async getmembers() {
|
||||||
|
if (this.ws) {
|
||||||
|
this.waitingmembers.forEach(async (value, guildid) => {
|
||||||
|
const keys = value.keys();
|
||||||
|
if (this.fetchingmembers.has(guildid)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const build = [];
|
||||||
|
for (const key of keys) {
|
||||||
|
build.push(key);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
let res;
|
||||||
|
const promise = new Promise((r) => {
|
||||||
|
res = r;
|
||||||
|
});
|
||||||
|
this.ws.send(JSON.stringify({
|
||||||
|
op: 8,
|
||||||
|
d: {
|
||||||
|
query: "",
|
||||||
|
user_ids: build,
|
||||||
|
guild_id: guildid,
|
||||||
|
limit: 100,
|
||||||
|
nonce: "" + Math.floor(Math.random() * 100000000)
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
this.fetchingmembers.set(guildid, res);
|
||||||
|
const data = await promise;
|
||||||
|
for (const thing of data) {
|
||||||
|
value.get(thing.id)(thing);
|
||||||
|
value.delete(thing.id);
|
||||||
|
}
|
||||||
|
this.getmembers();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export { Localuser };
|
export { Localuser };
|
||||||
|
|
|
@ -101,6 +101,7 @@ class Member {
|
||||||
}
|
}
|
||||||
const prom1 = fetch(guild.info.api.toString() + "/users/" + id + "/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id=" + guild.snowflake, { headers: guild.headers });
|
const prom1 = fetch(guild.info.api.toString() + "/users/" + id + "/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id=" + guild.snowflake, { headers: guild.headers });
|
||||||
prom1.catch(_ => { console.log(_); });
|
prom1.catch(_ => { console.log(_); });
|
||||||
|
guild.localuser.resolvemember(id?.id, guild.id);
|
||||||
const promoise = prom1.then(_ => _.json()).then(json => {
|
const promoise = prom1.then(_ => _.json()).then(json => {
|
||||||
const memb = new Member(json, guild);
|
const memb = new Member(json, guild);
|
||||||
Member.already[guild.id][id] = memb;
|
Member.already[guild.id][id] = memb;
|
||||||
|
|
2
EmojiList/credit.txt
Normal file
2
EmojiList/credit.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
https://github.com/muan/unicode-emoji-json/
|
||||||
|
the list is from here, though the actual file isn't included, if you want to compile the binary yourself, just put data-by-group.json in this file and run the needed script.
|
115
emoji-packer.js
Normal file
115
emoji-packer.js
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
const emojilist=require("./EmojiList/data-by-group.json");
|
||||||
|
console.log(emojilist);
|
||||||
|
|
||||||
|
const buffer=new ArrayBuffer(2**26);
|
||||||
|
const view = new DataView(buffer, 0);
|
||||||
|
let i=0;
|
||||||
|
function write16(numb){
|
||||||
|
view.setUint16(i,numb);
|
||||||
|
i+=2;
|
||||||
|
}
|
||||||
|
function write8(numb){
|
||||||
|
view.setUint8(i,numb);
|
||||||
|
i+=1;
|
||||||
|
}
|
||||||
|
function writeString8(str){
|
||||||
|
const encode=new TextEncoder("utf-8").encode(str);
|
||||||
|
write8(encode.length);
|
||||||
|
for(const thing of encode){
|
||||||
|
write8(thing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function writeString16(str){
|
||||||
|
const encode=new TextEncoder("utf-8").encode(str);
|
||||||
|
write16(encode.length);
|
||||||
|
for(const thing of encode){
|
||||||
|
write8(thing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function writeStringNo(str){
|
||||||
|
const encode=new TextEncoder("utf-8").encode(str);
|
||||||
|
for(const thing of encode){
|
||||||
|
write8(thing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write16(emojilist.length);
|
||||||
|
for(const thing of emojilist){
|
||||||
|
writeString16(thing.name);
|
||||||
|
write16(thing.emojis.length);
|
||||||
|
for(const emoji of thing.emojis){
|
||||||
|
writeString8(emoji.name);
|
||||||
|
write8(new TextEncoder("utf-8").encode(emoji.emoji).length+128*emoji.skin_tone_support);
|
||||||
|
writeStringNo(emoji.emoji);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const out=new ArrayBuffer(i);
|
||||||
|
const ar=new Uint8Array(out);
|
||||||
|
const br=new Uint8Array(buffer)
|
||||||
|
for(const thing in ar){
|
||||||
|
ar[thing]=br[thing];
|
||||||
|
}
|
||||||
|
console.log(i,ar);
|
||||||
|
|
||||||
|
function decodeEmojiList(buffer){
|
||||||
|
const view = new DataView(buffer, 0);
|
||||||
|
let i=0;
|
||||||
|
function read16(){
|
||||||
|
const int=view.getUint16(i);
|
||||||
|
i+=2;
|
||||||
|
return int;
|
||||||
|
}
|
||||||
|
function read8(){
|
||||||
|
const int=view.getUint8(i);
|
||||||
|
i+=1;
|
||||||
|
return int;
|
||||||
|
}
|
||||||
|
function readString8(){
|
||||||
|
return readStringNo(read8());
|
||||||
|
}
|
||||||
|
function readString16(){
|
||||||
|
return readStringNo(read16());
|
||||||
|
}
|
||||||
|
function readStringNo(length){
|
||||||
|
const array=new Uint8Array(length);
|
||||||
|
|
||||||
|
for(let i=0;i<length;i++){
|
||||||
|
array[i]=read8();
|
||||||
|
}
|
||||||
|
const decoded=new TextDecoder("utf-8").decode(array.buffer);;
|
||||||
|
|
||||||
|
//console.log(array);
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
const build=[];
|
||||||
|
let cats=read16();
|
||||||
|
|
||||||
|
for(;cats!==0;cats--){
|
||||||
|
const name=readString16();
|
||||||
|
const emojis=[];
|
||||||
|
let emojinumber=read16();
|
||||||
|
for(;emojinumber!==0;emojinumber--){
|
||||||
|
//console.log(emojis);
|
||||||
|
const name=readString8();
|
||||||
|
const len=read8();
|
||||||
|
const skin_tone_support=len>127;
|
||||||
|
const emoji=readStringNo(len-skin_tone_support*128);
|
||||||
|
emojis.push({
|
||||||
|
name,
|
||||||
|
skin_tone_support,
|
||||||
|
emoji
|
||||||
|
})
|
||||||
|
}
|
||||||
|
build.push({
|
||||||
|
name,
|
||||||
|
emojis
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return build;
|
||||||
|
}
|
||||||
|
console.log(JSON.stringify(decodeEmojiList(out)));
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
fs.writeFile("./webpage/emoji.bin",new Uint8Array(out),_=>{
|
||||||
|
|
||||||
|
});
|
|
@ -11,7 +11,8 @@ import { Role } from "./role.js";
|
||||||
import {InfiniteScroller} from "./infiniteScroller.js";
|
import {InfiniteScroller} from "./infiniteScroller.js";
|
||||||
import { SnowFlake } from "./snowflake.js";
|
import { SnowFlake } from "./snowflake.js";
|
||||||
import { channeljson, messagejson, readyjson } from "./jsontypes.js";
|
import { channeljson, messagejson, readyjson } from "./jsontypes.js";
|
||||||
|
import {Emoji} from "./emoji.js";
|
||||||
|
new Emoji();
|
||||||
declare global {
|
declare global {
|
||||||
interface NotificationOptions {
|
interface NotificationOptions {
|
||||||
image?: string
|
image?: string
|
||||||
|
|
BIN
webpage/emoji.bin
Normal file
BIN
webpage/emoji.bin
Normal file
Binary file not shown.
75
webpage/emoji.ts
Normal file
75
webpage/emoji.ts
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
class Emoji{
|
||||||
|
static emojis:{
|
||||||
|
name:string,
|
||||||
|
emojis:{
|
||||||
|
name:string,
|
||||||
|
emoji:string,
|
||||||
|
}[]
|
||||||
|
}[];
|
||||||
|
static decodeEmojiList(buffer:ArrayBuffer){
|
||||||
|
const view = new DataView(buffer, 0);
|
||||||
|
let i=0;
|
||||||
|
function read16(){
|
||||||
|
const int=view.getUint16(i);
|
||||||
|
i+=2;
|
||||||
|
return int;
|
||||||
|
}
|
||||||
|
function read8(){
|
||||||
|
const int=view.getUint8(i);
|
||||||
|
i+=1;
|
||||||
|
return int;
|
||||||
|
}
|
||||||
|
function readString8(){
|
||||||
|
return readStringNo(read8());
|
||||||
|
}
|
||||||
|
function readString16(){
|
||||||
|
return readStringNo(read16());
|
||||||
|
}
|
||||||
|
function readStringNo(length:number){
|
||||||
|
const array=new Uint8Array(length);
|
||||||
|
|
||||||
|
for(let i=0;i<length;i++){
|
||||||
|
array[i]=read8();
|
||||||
|
}
|
||||||
|
const decoded=new TextDecoder("utf-8").decode(array.buffer);;
|
||||||
|
|
||||||
|
//console.log(array);
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
const build:{name:string,emojis:{name:string,emoji:string}[]}[]=[];
|
||||||
|
let cats=read16();
|
||||||
|
|
||||||
|
for(;cats!==0;cats--){
|
||||||
|
const name=readString16();
|
||||||
|
const emojis=[];
|
||||||
|
let emojinumber=read16();
|
||||||
|
for(;emojinumber!==0;emojinumber--){
|
||||||
|
//console.log(emojis);
|
||||||
|
const name=readString8();
|
||||||
|
const len=read8();
|
||||||
|
const skin_tone_support=len>127;
|
||||||
|
const emoji=readStringNo(len-(+skin_tone_support*128));
|
||||||
|
emojis.push({
|
||||||
|
name,
|
||||||
|
skin_tone_support,
|
||||||
|
emoji
|
||||||
|
})
|
||||||
|
}
|
||||||
|
build.push({
|
||||||
|
name,
|
||||||
|
emojis
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.emojis=build;
|
||||||
|
console.log(build);
|
||||||
|
}
|
||||||
|
static grabEmoji(){
|
||||||
|
fetch("/emoji.bin").then(e=>{
|
||||||
|
return e.arrayBuffer()
|
||||||
|
}).then(e=>{
|
||||||
|
Emoji.decodeEmojiList(e);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Emoji.grabEmoji();
|
||||||
|
export {Emoji};
|
|
@ -7,7 +7,7 @@ import {Fullscreen} from "./fullscreen.js";
|
||||||
import {setTheme, Specialuser} from "./login.js";
|
import {setTheme, Specialuser} from "./login.js";
|
||||||
import { SnowFlake } from "./snowflake.js";
|
import { SnowFlake } from "./snowflake.js";
|
||||||
import { Message } from "./message.js";
|
import { Message } from "./message.js";
|
||||||
import { channeljson, readyjson, userjson } from "./jsontypes.js";
|
import { channeljson, guildjson, memberjson, readyjson, userjson } from "./jsontypes.js";
|
||||||
|
|
||||||
const wsCodesRetry=new Set([4000,4003,4005,4007,4008,4009]);
|
const wsCodesRetry=new Set([4000,4003,4005,4007,4008,4009]);
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ class Localuser{
|
||||||
}
|
}
|
||||||
|
|
||||||
}else if(temp.op===10){
|
}else if(temp.op===10){
|
||||||
console.log("heartbeat down")
|
console.log("heartbeat down");
|
||||||
this.wsinterval=setInterval(_=>{
|
this.wsinterval=setInterval(_=>{
|
||||||
if (this.connectionSucceed===0) this.connectionSucceed=Date.now()
|
if (this.connectionSucceed===0) this.connectionSucceed=Date.now()
|
||||||
|
|
||||||
|
@ -375,7 +375,7 @@ class Localuser{
|
||||||
div.classList.add("home","servericon");
|
div.classList.add("home","servericon");
|
||||||
|
|
||||||
img.src="/icons/home.svg";
|
img.src="/icons/home.svg";
|
||||||
img.classList.add("svgtheme")
|
img.classList.add("svgtheme","svgicon")
|
||||||
img["all"]=this.guildids.get("@me");
|
img["all"]=this.guildids.get("@me");
|
||||||
this.guildids.get("@me").html=outdiv;
|
this.guildids.get("@me").html=outdiv;
|
||||||
const unread=document.createElement("div");
|
const unread=document.createElement("div");
|
||||||
|
@ -422,7 +422,7 @@ class Localuser{
|
||||||
const guilddsdiv=document.createElement("div");
|
const guilddsdiv=document.createElement("div");
|
||||||
const guildDiscoveryContainer=document.createElement("img");
|
const guildDiscoveryContainer=document.createElement("img");
|
||||||
guildDiscoveryContainer.src="/icons/explore.svg";
|
guildDiscoveryContainer.src="/icons/explore.svg";
|
||||||
guildDiscoveryContainer.classList.add("svgtheme");
|
guildDiscoveryContainer.classList.add("svgtheme","svgicon");
|
||||||
guilddsdiv.classList.add("home","servericon");
|
guilddsdiv.classList.add("home","servericon");
|
||||||
guilddsdiv.appendChild(guildDiscoveryContainer);
|
guilddsdiv.appendChild(guildDiscoveryContainer);
|
||||||
serverlist.appendChild(guilddsdiv);
|
serverlist.appendChild(guilddsdiv);
|
||||||
|
@ -964,5 +964,55 @@ class Localuser{
|
||||||
);
|
);
|
||||||
botDialog.show();
|
botDialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------- resolving members code -----------
|
||||||
|
waitingmembers:Map<string,Map<string,(returns:memberjson|undefined)=>void>>=new Map();
|
||||||
|
async resolvemember(id:string,guildid:string):Promise<memberjson|undefined>{
|
||||||
|
console.warn("this function is currently non-functional, either due to a bug in the client or the server, it's currently unclear, use at your own risk");
|
||||||
|
if(!this.waitingmembers.has(guildid)){
|
||||||
|
this.waitingmembers.set(guildid,new Map());
|
||||||
|
}
|
||||||
|
let res:(returns:memberjson|undefined)=>void;
|
||||||
|
const promise:Promise<memberjson|undefined>=new Promise((r)=>{
|
||||||
|
res=r;
|
||||||
|
})
|
||||||
|
this.waitingmembers.get(guildid).set(id,res);
|
||||||
|
this.getmembers();
|
||||||
|
return await promise;
|
||||||
|
}
|
||||||
|
fetchingmembers:Map<string,(r:memberjson[])=>void>=new Map();
|
||||||
|
async getmembers(){
|
||||||
|
if(this.ws){
|
||||||
|
this.waitingmembers.forEach(async (value,guildid)=>{
|
||||||
|
const keys=value.keys();
|
||||||
|
if(this.fetchingmembers.has(guildid)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const build:string[]=[];
|
||||||
|
for(const key of keys){build.push(key)};
|
||||||
|
let res:(r:memberjson[])=>void;
|
||||||
|
const promise:Promise<memberjson[]>=new Promise((r)=>{
|
||||||
|
res=r;
|
||||||
|
})
|
||||||
|
this.ws.send(JSON.stringify({
|
||||||
|
op:8,
|
||||||
|
d:{
|
||||||
|
query:"",
|
||||||
|
user_ids:build,
|
||||||
|
guild_id:guildid,
|
||||||
|
limit:100,
|
||||||
|
nonce:""+Math.floor(Math.random()*100000000)
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
this.fetchingmembers.set(guildid,res);
|
||||||
|
const data=await promise;
|
||||||
|
for(const thing of data){
|
||||||
|
value.get(thing.id)(thing);
|
||||||
|
value.delete(thing.id);
|
||||||
|
}
|
||||||
|
this.getmembers();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export {Localuser};
|
export {Localuser};
|
||||||
|
|
|
@ -94,6 +94,7 @@ class Member{
|
||||||
}
|
}
|
||||||
const prom1= fetch(guild.info.api.toString()+"/users/"+id+"/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id="+guild.snowflake,{headers:guild.headers})
|
const prom1= fetch(guild.info.api.toString()+"/users/"+id+"/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id="+guild.snowflake,{headers:guild.headers})
|
||||||
prom1.catch(_=>{console.log(_)})
|
prom1.catch(_=>{console.log(_)})
|
||||||
|
guild.localuser.resolvemember(id?.id,guild.id);
|
||||||
const promoise=prom1.then(_=>_.json()).then(json=>{
|
const promoise=prom1.then(_=>_.json()).then(json=>{
|
||||||
const memb=new Member(json,guild);
|
const memb=new Member(json,guild);
|
||||||
Member.already[guild.id][id]=memb;
|
Member.already[guild.id][id]=memb;
|
||||||
|
|
|
@ -1532,3 +1532,7 @@ form div{
|
||||||
.hiddencat{
|
.hiddencat{
|
||||||
rotate:-90deg;
|
rotate:-90deg;
|
||||||
}
|
}
|
||||||
|
.svgicon{
|
||||||
|
width:.5in;
|
||||||
|
height:.5in;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue