From f36aa1f40dd92a2dfe4f3e92bfc26a67d08ae2be Mon Sep 17 00:00:00 2001 From: Dessalines Date: Wed, 11 Mar 2020 19:10:10 -0400 Subject: [PATCH 1/5] Show full scores on hover for posts and comments. Fixes #592 --- ui/src/components/comment-node.tsx | 22 +++++++++++++++++++--- ui/src/components/post-listing.tsx | 26 ++++++++++++++++++++------ ui/src/utils.ts | 10 +++++----- ui/translations/en.json | 4 ++++ 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/ui/src/components/comment-node.tsx b/ui/src/components/comment-node.tsx index 524367bce..32e43fdc7 100644 --- a/ui/src/components/comment-node.tsx +++ b/ui/src/components/comment-node.tsx @@ -198,9 +198,7 @@ export class CommentNode extends Component { @@ -916,6 +914,7 @@ export class CommentNode extends Component { WebSocketService.Instance.likeComment(form); this.setState(this.state); + setupTippy(); } handleCommentDownvote(i: CommentNodeI) { @@ -943,6 +942,7 @@ export class CommentNode extends Component { WebSocketService.Instance.likeComment(form); this.setState(this.state); + setupTippy(); } handleModRemoveShow(i: CommentNode) { @@ -1166,4 +1166,20 @@ export class CommentNode extends Component { return 'text-muted'; } } + + get pointsTippy(): string { + let points = i18n.t('number_of_points', { + count: this.state.score, + }); + + let upvotes = i18n.t('number_of_upvotes', { + count: this.state.upvotes, + }); + + let downvotes = i18n.t('number_of_downvotes', { + count: this.state.downvotes, + }); + + return `${points} • ${upvotes} • ${downvotes}`; + } } diff --git a/ui/src/components/post-listing.tsx b/ui/src/components/post-listing.tsx index bef74999f..fd34875d7 100644 --- a/ui/src/components/post-listing.tsx +++ b/ui/src/components/post-listing.tsx @@ -262,9 +262,7 @@ export class PostListing extends Component {
{this.state.score}
@@ -466,9 +464,7 @@ export class PostListing extends Component { <>
  • @@ -1022,6 +1018,7 @@ export class PostListing extends Component { WebSocketService.Instance.likePost(form); i.setState(i.state); + setupTippy(); } handlePostDisLike(i: PostListing) { @@ -1048,6 +1045,7 @@ export class PostListing extends Component { WebSocketService.Instance.likePost(form); i.setState(i.state); + setupTippy(); } handleEditClick(i: PostListing) { @@ -1291,4 +1289,20 @@ export class PostListing extends Component { i.setState(i.state); setupTippy(); } + + get pointsTippy(): string { + let points = i18n.t('number_of_points', { + count: this.state.score, + }); + + let upvotes = i18n.t('number_of_upvotes', { + count: this.state.upvotes, + }); + + let downvotes = i18n.t('number_of_downvotes', { + count: this.state.downvotes, + }); + + return `${points} • ${upvotes} • ${downvotes}`; + } } diff --git a/ui/src/utils.ts b/ui/src/utils.ts index 27dbfb500..69666200d 100644 --- a/ui/src/utils.ts +++ b/ui/src/utils.ts @@ -16,7 +16,7 @@ import 'moment/locale/ja'; import { UserOperation, Comment, - CommentNode, + CommentNode as CommentNodeI, Post, PrivateMessage, User, @@ -668,15 +668,15 @@ export function editPostRes(data: PostResponse, post: Post) { export function commentsToFlatNodes( comments: Array -): Array { - let nodes: Array = []; +): Array { + let nodes: Array = []; for (let comment of comments) { nodes.push({ comment: comment }); } return nodes; } -export function commentSort(tree: Array, sort: CommentSortType) { +export function commentSort(tree: Array, sort: CommentSortType) { // First, put removed and deleted comments at the bottom, then do your other sorts if (sort == CommentSortType.Top) { tree.sort( @@ -716,7 +716,7 @@ export function commentSort(tree: Array, sort: CommentSortType) { } } -export function commentSortSortType(tree: Array, sort: SortType) { +export function commentSortSortType(tree: Array, sort: SortType) { commentSort(tree, convertCommentSortType(sort)); } diff --git a/ui/translations/en.json b/ui/translations/en.json index afee21bbe..e9df20ba3 100644 --- a/ui/translations/en.json +++ b/ui/translations/en.json @@ -155,7 +155,11 @@ "downvotes_disabled": "Downvotes disabled", "enable_downvotes": "Enable Downvotes", "upvote": "Upvote", + "number_of_upvotes": "{{count}} Upvote", + "number_of_upvotes_plural": "{{count}} Upvotes", "downvote": "Downvote", + "number_of_downvotes": "{{count}} Downvote", + "number_of_downvotes_plural": "{{count}} Downvotes", "open_registration": "Open Registration", "registration_closed": "Registration closed", "enable_nsfw": "Enable NSFW", From ef6df1339f6d612ad466f90d5438749e6ebfb6d7 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Thu, 12 Mar 2020 12:03:04 +0100 Subject: [PATCH 2/5] Proper error logging for websocket --- server/Cargo.lock | 1 + server/Cargo.toml | 1 + server/src/websocket/server.rs | 18 +++++++++++------- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index a39dcd641..a58e0438b 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -1448,6 +1448,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lettre 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "lettre_email 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/server/Cargo.toml b/server/Cargo.toml index e73143687..10c0dfc81 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -19,6 +19,7 @@ actix-web = "2.0.0" actix-files = "0.2.1" actix-web-actors = "2.0.0" actix-rt = "1.0.0" +log = "0.4.0" env_logger = "0.7.1" rand = "0.7.3" strum = "0.17.1" diff --git a/server/src/websocket/server.rs b/server/src/websocket/server.rs index 1cbcb34fb..e200b1b99 100644 --- a/server/src/websocket/server.rs +++ b/server/src/websocket/server.rs @@ -6,6 +6,7 @@ use actix::prelude::*; use diesel::r2d2::{ConnectionManager, Pool, PooledConnection}; use diesel::PgConnection; use failure::Error; +use log::warn; use rand::{rngs::ThreadRng, Rng}; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -448,13 +449,16 @@ impl Handler for ChatServer { type Result = MessageResult; fn handle(&mut self, msg: StandardMessage, _: &mut Context) -> Self::Result { - let msg_out = match parse_json_message(self, msg) { - Ok(m) => m, - Err(e) => e.to_string(), - }; - - println!("Message Sent: {}", msg_out); - MessageResult(msg_out) + match parse_json_message(self, msg) { + Ok(m) => { + println!("Message Sent: {}", m); + MessageResult(m) + } + Err(e) => { + warn!("Error during message handling {}", e); + MessageResult(e.to_string()) + } + } } } From 62ab68d317b9673ba1e3d485393aba310cda3b15 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 13 Mar 2020 11:08:42 -0400 Subject: [PATCH 3/5] Adding full logging. --- .dockerignore | 1 + ansible/templates/docker-compose.yml | 4 +++- docker/dev/docker-compose.yml | 2 ++ docker/prod/docker-compose.yml | 2 ++ install.sh | 4 ++-- server/src/api/comment.rs | 11 ++++++----- server/src/api/user.rs | 3 ++- server/src/lib.rs | 5 +++-- server/src/routes/websocket.rs | 13 ++++++------- server/src/websocket/server.rs | 10 +++++----- 10 files changed, 32 insertions(+), 23 deletions(-) diff --git a/.dockerignore b/.dockerignore index 4288d3cb5..d7177be49 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,4 +2,5 @@ ui/node_modules ui/dist server/target docker/dev/volumes +docker/federation-test/volumes .git diff --git a/ansible/templates/docker-compose.yml b/ansible/templates/docker-compose.yml index 57ee142a6..ffd5b9c2b 100644 --- a/ansible/templates/docker-compose.yml +++ b/ansible/templates/docker-compose.yml @@ -6,6 +6,8 @@ services: ports: - "127.0.0.1:8536:8536" restart: always + environment: + - RUST_LOG=debug volumes: - ./lemmy.hjson:/config/config.hjson:ro depends_on: @@ -43,4 +45,4 @@ services: image: mwader/postfix-relay environment: - POSTFIX_myhostname={{ domain }} - restart: "always" \ No newline at end of file + restart: "always" diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml index 64ba1db43..a7d289b21 100644 --- a/docker/dev/docker-compose.yml +++ b/docker/dev/docker-compose.yml @@ -18,6 +18,8 @@ services: ports: - "127.0.0.1:8536:8536" restart: always + environment: + - RUST_LOG=debug volumes: - ../lemmy.hjson:/config/config.hjson:ro depends_on: diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml index 70c6bfe70..9f5e89259 100644 --- a/docker/prod/docker-compose.yml +++ b/docker/prod/docker-compose.yml @@ -16,6 +16,8 @@ services: ports: - "127.0.0.1:8536:8536" restart: always + environment: + - RUST_LOG=debug volumes: - ./lemmy.hjson:/config/config.hjson:ro depends_on: diff --git a/install.sh b/install.sh index b368891cf..ad3e4ab3a 100755 --- a/install.sh +++ b/install.sh @@ -16,7 +16,7 @@ init_db_final=0 while [ "$init_db_valid" == 0 ] do read -p "Initialize database (y/n)? " init_db - case "${init_db,,}" in + case "${init_db,,}" in y|yes ) init_db_valid=1; init_db_final=1;; n|no ) init_db_valid=1; init_db_final=0;; * ) echo "Invalid input" 1>&2;; @@ -37,7 +37,7 @@ yarn build # Build and run the backend cd ../server -cargo run +RUST_LOG=debug cargo run # For live coding, where both the front and back end, automagically reload on any save, do: # cd ui && yarn start diff --git a/server/src/api/comment.rs b/server/src/api/comment.rs index 5c6149666..8373a338b 100644 --- a/server/src/api/comment.rs +++ b/server/src/api/comment.rs @@ -2,6 +2,7 @@ use super::*; use crate::send_email; use crate::settings::Settings; use diesel::PgConnection; +use log::error; use std::str::FromStr; #[derive(Serialize, Deserialize)] @@ -128,7 +129,7 @@ impl Perform for Oper { // Let the uniqueness handle this fail match UserMention::create(&conn, &user_mention_form) { Ok(_mention) => (), - Err(_e) => eprintln!("{}", &_e), + Err(_e) => error!("{}", &_e), }; // Send an email to those users that have notifications on @@ -145,7 +146,7 @@ impl Perform for Oper { ); match send_email(subject, &mention_email, &mention_user.name, html) { Ok(_o) => _o, - Err(e) => eprintln!("{}", e), + Err(e) => error!("{}", e), }; } } @@ -174,7 +175,7 @@ impl Perform for Oper { ); match send_email(subject, &comment_reply_email, &parent_user.name, html) { Ok(_o) => _o, - Err(e) => eprintln!("{}", e), + Err(e) => error!("{}", e), }; } } @@ -199,7 +200,7 @@ impl Perform for Oper { ); match send_email(subject, &post_reply_email, &parent_user.name, html) { Ok(_o) => _o, - Err(e) => eprintln!("{}", e), + Err(e) => error!("{}", e), }; } } @@ -318,7 +319,7 @@ impl Perform for Oper { // Let the uniqueness handle this fail match UserMention::create(&conn, &user_mention_form) { Ok(_mention) => (), - Err(_e) => eprintln!("{}", &_e), + Err(_e) => error!("{}", &_e), } } } diff --git a/server/src/api/user.rs b/server/src/api/user.rs index f73138953..333fd9494 100644 --- a/server/src/api/user.rs +++ b/server/src/api/user.rs @@ -3,6 +3,7 @@ use crate::settings::Settings; use crate::{generate_random_string, send_email}; use bcrypt::verify; use diesel::PgConnection; +use log::error; use std::str::FromStr; #[derive(Serialize, Deserialize, Debug)] @@ -1008,7 +1009,7 @@ impl Perform for Oper { ); match send_email(subject, &email, &recipient_user.name, html) { Ok(_o) => _o, - Err(e) => eprintln!("{}", e), + Err(e) => error!("{}", e), }; } } diff --git a/server/src/lib.rs b/server/src/lib.rs index f437c200b..eeaadb63a 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -39,6 +39,7 @@ use lettre::smtp::extension::ClientId; use lettre::smtp::ConnectionReuseParameters; use lettre::{ClientSecurity, SmtpClient, Transport}; use lettre_email::Email; +use log::error; use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use rand::distributions::Alphanumeric; use rand::{thread_rng, Rng}; @@ -190,7 +191,7 @@ fn fetch_iframely_and_pictshare_data( Some(url) => match fetch_iframely(&url) { Ok(res) => (res.title, res.description, res.thumbnail_url, res.html), Err(e) => { - eprintln!("iframely err: {}", e); + error!("iframely err: {}", e); (None, None, None, None) } }, @@ -202,7 +203,7 @@ fn fetch_iframely_and_pictshare_data( Some(iframely_thumbnail_url) => match fetch_pictshare(&iframely_thumbnail_url) { Ok(res) => Some(res.url), Err(e) => { - eprintln!("pictshare err: {}", e); + error!("pictshare err: {}", e); None } }, diff --git a/server/src/routes/websocket.rs b/server/src/routes/websocket.rs index a68b2bcde..6c4326fd3 100644 --- a/server/src/routes/websocket.rs +++ b/server/src/routes/websocket.rs @@ -3,6 +3,7 @@ use actix::prelude::*; use actix_web::web; use actix_web::*; use actix_web_actors::ws; +use log::{error, info}; use std::time::{Duration, Instant}; pub fn config(cfg: &mut web::ServiceConfig) { @@ -99,7 +100,6 @@ impl Handler for WSSession { type Result = (); fn handle(&mut self, msg: WSMessage, ctx: &mut Self::Context) { - // println!("id: {} msg: {}", self.id, msg.0); ctx.text(msg.0); } } @@ -107,11 +107,10 @@ impl Handler for WSSession { /// WebSocket message handler impl StreamHandler> for WSSession { fn handle(&mut self, result: Result, ctx: &mut Self::Context) { - // println!("WEBSOCKET MESSAGE: {:?} from id: {}", msg, self.id); let message = match result { Ok(m) => m, Err(e) => { - println!("{}", e); + error!("{}", e); return; } }; @@ -125,7 +124,7 @@ impl StreamHandler> for WSSession { } ws::Message::Text(text) => { let m = text.trim().to_owned(); - println!("WEBSOCKET MESSAGE: {:?} from id: {}", &m, self.id); + info!("Message received: {:?} from id: {}", &m, self.id); self .cs_addr @@ -138,14 +137,14 @@ impl StreamHandler> for WSSession { match res { Ok(res) => ctx.text(res), Err(e) => { - eprintln!("{}", &e); + error!("{}", &e); } } actix::fut::ready(()) }) .wait(ctx); } - ws::Message::Binary(_bin) => println!("Unexpected binary"), + ws::Message::Binary(_bin) => info!("Unexpected binary"), ws::Message::Close(_) => { ctx.stop(); } @@ -163,7 +162,7 @@ impl WSSession { // check client heartbeats if Instant::now().duration_since(act.hb) > CLIENT_TIMEOUT { // heartbeat timed out - println!("Websocket Client heartbeat failed, disconnecting!"); + error!("Websocket Client heartbeat failed, disconnecting!"); // notify chat server act.cs_addr.do_send(Disconnect { diff --git a/server/src/websocket/server.rs b/server/src/websocket/server.rs index e200b1b99..831f12ee1 100644 --- a/server/src/websocket/server.rs +++ b/server/src/websocket/server.rs @@ -6,7 +6,7 @@ use actix::prelude::*; use diesel::r2d2::{ConnectionManager, Pool, PooledConnection}; use diesel::PgConnection; use failure::Error; -use log::warn; +use log::{error, info, warn}; use rand::{rngs::ThreadRng, Rng}; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -344,7 +344,7 @@ impl ChatServer { } if rate_limit.allowance < 1.0 { - println!( + warn!( "Rate limited IP: {}, time_passed: {}, allowance: {}", &info.ip, time_passed, rate_limit.allowance ); @@ -388,7 +388,7 @@ impl Handler for ChatServer { fn handle(&mut self, msg: Connect, _ctx: &mut Context) -> Self::Result { // register session with random id let id = self.rng.gen::(); - println!("{} joined", &msg.ip); + info!("{} joined", &msg.ip); self.sessions.insert( id, @@ -451,11 +451,11 @@ impl Handler for ChatServer { fn handle(&mut self, msg: StandardMessage, _: &mut Context) -> Self::Result { match parse_json_message(self, msg) { Ok(m) => { - println!("Message Sent: {}", m); + info!("Message Sent: {}", m); MessageResult(m) } Err(e) => { - warn!("Error during message handling {}", e); + error!("Error during message handling {}", e); MessageResult(e.to_string()) } } From 74eae88e37d1ee5e4c74cdf7be9662f4b9626902 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Mar 2020 23:05:52 +0000 Subject: [PATCH 4/5] Bump acorn from 5.7.3 to 5.7.4 in /ui Bumps [acorn](https://github.com/acornjs/acorn) from 5.7.3 to 5.7.4. - [Release notes](https://github.com/acornjs/acorn/releases) - [Commits](https://github.com/acornjs/acorn/compare/5.7.3...5.7.4) Signed-off-by: dependabot[bot] --- ui/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/yarn.lock b/ui/yarn.lock index d36bef04e..0d382f8f1 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -258,9 +258,9 @@ acorn-jsx@^5.1.0: integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== acorn@^5.0.3, acorn@^5.7.3: - version "5.7.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== + version "5.7.4" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" + integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== acorn@^7.1.0: version "7.1.0" From 1a7c6fbd324c662e682c491915f8995262c21d3d Mon Sep 17 00:00:00 2001 From: Dessalines Date: Sun, 15 Mar 2020 13:02:14 -0400 Subject: [PATCH 5/5] Add theming guide. Fixes #596 --- .gitignore | 3 +- docs/src/SUMMARY.md | 1 + docs/src/contributing_theming.md | 18 +++++++++ ui/src/utils.ts | 66 ++++++++++++++++---------------- 4 files changed, 54 insertions(+), 34 deletions(-) create mode 100644 docs/src/contributing_theming.md diff --git a/.gitignore b/.gitignore index d823aacab..9f7fa1e3c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ docker/dev/env_deploy.sh build/ .idea/ ui/src/translations -docker/dev/volumes \ No newline at end of file +docker/dev/volumes +docker/federation-test/volumes diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 9a2ecde8d..10a6153ea 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -15,4 +15,5 @@ - [Local Development](contributing_local_development.md) - [Websocket/HTTP API](contributing_websocket_http_api.md) - [ActivityPub API Outline](contributing_apub_api_outline.md) + - [Theming Guide](contributing_theming.md) - [Lemmy Council](lemmy_council.md) diff --git a/docs/src/contributing_theming.md b/docs/src/contributing_theming.md new file mode 100644 index 000000000..25c8ca6d1 --- /dev/null +++ b/docs/src/contributing_theming.md @@ -0,0 +1,18 @@ +# Theming Guide + +Lemmy uses [Bootstrap v4](https://getbootstrap.com/), and very few custom css classes, so any bootstrap v4 compatible theme should work fine. + +## Creating + +- Use a tool like [bootstrap.build](https://bootstrap.build/) to create a bootstrap v4 theme. Export the `bootstrap.min.css` once you're done, and save the `_variables.scss` too. + +## Testing + +- To test out a theme, you can either use your browser's web tools, or a plugin like stylus to copy-paste a theme, when viewing Lemmy. + +## Adding + +1. Copy `{my-theme-name}.min.css` to `ui/assets/css/themes`. (You can also copy the `_variables.scss` here if you want). +1. Go to `ui/src/utils.ts` and add `{my-theme-name}` to the themes list. +1. Test locally +1. Do a pull request with those changes. diff --git a/ui/src/utils.ts b/ui/src/utils.ts index 69666200d..89fbe51c8 100644 --- a/ui/src/utils.ts +++ b/ui/src/utils.ts @@ -53,6 +53,39 @@ export const postRefetchSeconds: number = 60 * 1000; export const fetchLimit: number = 20; export const mentionDropdownFetchLimit = 10; +export const languages = [ + { code: 'ca', name: 'Català' }, + { code: 'en', name: 'English' }, + { code: 'eo', name: 'Esperanto' }, + { code: 'es', name: 'Español' }, + { code: 'de', name: 'Deutsch' }, + { code: 'fa', name: 'فارسی' }, + { code: 'ja', name: '日本語' }, + { code: 'pt_BR', name: 'Português Brasileiro' }, + { code: 'zh', name: '中文' }, + { code: 'fi', name: 'Suomi' }, + { code: 'fr', name: 'Français' }, + { code: 'sv', name: 'Svenska' }, + { code: 'ru', name: 'Русский' }, + { code: 'nl', name: 'Nederlands' }, + { code: 'it', name: 'Italiano' }, +]; + +export const themes = [ + 'litera', + 'materia', + 'minty', + 'solar', + 'united', + 'cyborg', + 'darkly', + 'journal', + 'sketchy', + 'vaporwave', + 'vaporwave-dark', + 'i386', +]; + export function randomStr() { return Math.random() .toString(36) @@ -275,24 +308,6 @@ export function debounce( }; } -export const languages = [ - { code: 'ca', name: 'Català' }, - { code: 'en', name: 'English' }, - { code: 'eo', name: 'Esperanto' }, - { code: 'es', name: 'Español' }, - { code: 'de', name: 'Deutsch' }, - { code: 'fa', name: 'فارسی' }, - { code: 'ja', name: '日本語' }, - { code: 'pt_BR', name: 'Português Brasileiro' }, - { code: 'zh', name: '中文' }, - { code: 'fi', name: 'Suomi' }, - { code: 'fr', name: 'Français' }, - { code: 'sv', name: 'Svenska' }, - { code: 'ru', name: 'Русский' }, - { code: 'nl', name: 'Nederlands' }, - { code: 'it', name: 'Italiano' }, -]; - export function getLanguage(): string { let user = UserService.Instance.user; let lang = user && user.lang ? user.lang : 'browser'; @@ -344,21 +359,6 @@ export function getMomentLanguage(): string { return lang; } -export const themes = [ - 'litera', - 'materia', - 'minty', - 'solar', - 'united', - 'cyborg', - 'darkly', - 'journal', - 'sketchy', - 'vaporwave', - 'vaporwave-dark', - 'i386', -]; - export function setTheme(theme: string = 'darkly') { // unload all the other themes for (var i = 0; i < themes.length; i++) {