Adding 8 different themes.

- Fixes #276
pull/722/head
Dessalines 2019-10-15 12:21:27 -07:00
parent 37d4f84787
commit c0821fcaa5
35 changed files with 372 additions and 87 deletions

View File

@ -0,0 +1 @@
alter table user_ drop column theme;

View File

@ -0,0 +1 @@
alter table user_ add column theme varchar(20) default 'darkly' not null;

View File

@ -21,6 +21,7 @@ pub struct Register {
#[derive(Serialize, Deserialize)]
pub struct SaveUserSettings {
show_nsfw: bool,
theme: String,
auth: String,
}
@ -162,6 +163,7 @@ impl Perform<LoginResponse> for Oper<Register> {
admin: data.admin,
banned: false,
show_nsfw: data.show_nsfw,
theme: "darkly".into(),
};
// Create the user
@ -252,6 +254,7 @@ impl Perform<LoginResponse> for Oper<SaveUserSettings> {
admin: read_user.admin,
banned: read_user.banned,
show_nsfw: data.show_nsfw,
theme: data.theme.to_owned(),
};
let updated_user = match User_::update(&conn, user_id, &user_form) {
@ -416,6 +419,7 @@ impl Perform<AddAdminResponse> for Oper<AddAdmin> {
admin: data.added,
banned: read_user.banned,
show_nsfw: read_user.show_nsfw,
theme: read_user.theme,
};
match User_::update(&conn, data.user_id, &user_form) {
@ -474,6 +478,7 @@ impl Perform<BanUserResponse> for Oper<BanUser> {
admin: read_user.admin,
banned: data.ban,
show_nsfw: read_user.show_nsfw,
theme: read_user.theme,
};
match User_::update(&conn, data.user_id, &user_form) {

View File

@ -72,6 +72,7 @@ mod tests {
banned: false,
updated: None,
show_nsfw: false,
theme: "darkly".into(),
};
let person = expected_user.person();

View File

@ -178,6 +178,7 @@ mod tests {
banned: false,
updated: None,
show_nsfw: false,
theme: "darkly".into(),
};
let inserted_user = User_::create(&conn, &new_user).unwrap();

View File

@ -264,6 +264,7 @@ mod tests {
banned: false,
updated: None,
show_nsfw: false,
theme: "darkly".into(),
};
let inserted_user = User_::create(&conn, &new_user).unwrap();

View File

@ -264,6 +264,7 @@ mod tests {
banned: false,
updated: None,
show_nsfw: false,
theme: "darkly".into(),
};
let inserted_user = User_::create(&conn, &new_user).unwrap();

View File

@ -446,6 +446,7 @@ mod tests {
banned: false,
updated: None,
show_nsfw: false,
theme: "darkly".into(),
};
let inserted_mod = User_::create(&conn, &new_mod).unwrap();
@ -460,6 +461,7 @@ mod tests {
banned: false,
updated: None,
show_nsfw: false,
theme: "darkly".into(),
};
let inserted_user = User_::create(&conn, &new_user).unwrap();

View File

@ -191,6 +191,7 @@ mod tests {
banned: false,
updated: None,
show_nsfw: false,
theme: "darkly".into(),
};
let inserted_user = User_::create(&conn, &new_user).unwrap();

View File

@ -225,6 +225,7 @@ mod tests {
admin: false,
banned: false,
show_nsfw: false,
theme: "darkly".into(),
};
let inserted_user = User_::create(&conn, &new_user).unwrap();

View File

@ -20,6 +20,7 @@ pub struct User_ {
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
pub show_nsfw: bool,
pub theme: String,
}
#[derive(Insertable, AsChangeset, Clone)]
@ -34,6 +35,7 @@ pub struct UserForm {
pub email: Option<String>,
pub updated: Option<chrono::NaiveDateTime>,
pub show_nsfw: bool,
pub theme: String,
}
impl Crud<UserForm> for User_ {
@ -74,6 +76,7 @@ pub struct Claims {
pub username: String,
pub iss: String,
pub show_nsfw: bool,
pub theme: String,
}
impl Claims {
@ -94,6 +97,7 @@ impl User_ {
username: self.name.to_owned(),
iss: self.fedi_name.to_owned(),
show_nsfw: self.show_nsfw,
theme: self.theme.to_owned(),
};
encode(
&Header::default(),
@ -141,6 +145,7 @@ mod tests {
banned: false,
updated: None,
show_nsfw: false,
theme: "darkly".into(),
};
let inserted_user = User_::create(&conn, &new_user).unwrap();
@ -158,6 +163,7 @@ mod tests {
published: inserted_user.published,
updated: None,
show_nsfw: false,
theme: "darkly".into(),
};
let read_user = User_::read(&conn, inserted_user.id).unwrap();

View File

@ -254,6 +254,7 @@ table! {
published -> Timestamp,
updated -> Nullable<Timestamp>,
show_nsfw -> Bool,
theme -> Varchar,
}
}
@ -304,28 +305,28 @@ joinable!(site -> user_ (creator_id));
joinable!(user_ban -> user_ (user_id));
allow_tables_to_appear_in_same_query!(
category,
comment,
comment_like,
comment_saved,
community,
community_follower,
community_moderator,
community_user_ban,
mod_add,
mod_add_community,
mod_ban,
mod_ban_from_community,
mod_lock_post,
mod_remove_comment,
mod_remove_community,
mod_remove_post,
mod_sticky_post,
post,
post_like,
post_read,
post_saved,
site,
user_,
user_ban,
category,
comment,
comment_like,
comment_saved,
community,
community_follower,
community_moderator,
community_user_ban,
mod_add,
mod_add_community,
mod_ban,
mod_ban_from_community,
mod_lock_post,
mod_remove_comment,
mod_remove_community,
mod_remove_post,
mod_sticky_post,
post,
post_like,
post_read,
post_saved,
site,
user_,
user_ban,
);

View File

@ -1,7 +1,3 @@
body, .text-white, .navbar-brand, .badge-light, .btn-secondary {
color: #dedede !important;
}
.navbar-toggler {
border: 0px;
}
@ -31,29 +27,6 @@ body, .text-white, .navbar-brand, .badge-light, .btn-secondary {
margin-top: -10px;
}
.form-control, .form-control:focus {
background-color: var(--secondary);
color: #fff;
}
.form-control:disabled {
background-color: var(--secondary);
opacity: .5;
}
.custom-select {
color: #fff;
background-color: var(--secondary);
}
.mark {
background-color: #333;
}
.mark-two {
background-color: #444 !important;
}
.md-div p:last-child {
margin-bottom: 0px;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
ui/package.json vendored
View File

@ -21,6 +21,7 @@
"@types/markdown-it": "^0.0.7",
"@types/markdown-it-container": "^2.0.2",
"autosize": "^4.0.2",
"bootswatch": "^4.3.1",
"classcat": "^1.1.3",
"dotenv": "^6.1.0",
"emoji-short-name": "^0.1.0",

View File

@ -13,7 +13,7 @@ export class Footer extends Component<any, any> {
render() {
return (
<nav class="container navbar navbar-expand-md navbar-light navbar-bg p-0 px-3 my-2">
<nav class="container navbar navbar-expand-md navbar-light navbar-bg p-0 px-3 mt-2">
<div className="navbar-collapse">
<ul class="navbar-nav ml-auto">
<li class="nav-item">

View File

@ -96,8 +96,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
<div className="post-title">
<h5 className="mb-0 d-inline">
{post.url ?
<a className="text-white" href={post.url} target="_blank" title={post.url}>{post.name}</a> :
<Link className="text-white" to={`/post/${post.id}`} title={i18n.t('comments')}>{post.name}</Link>
<a className="text-body" href={post.url} target="_blank" title={post.url}>{post.name}</a> :
<Link className="text-body" to={`/post/${post.id}`} title={i18n.t('comments')}>{post.name}</Link>
}
</h5>
{post.url &&

View File

@ -74,7 +74,7 @@ export class Post extends Component<any, PostState> {
if (this.state.scrolled_comment_id && !this.state.scrolled && lastState.comments.length > 0) {
var elmnt = document.getElementById(`comment-${this.state.scrolled_comment_id}`);
elmnt.scrollIntoView();
elmnt.classList.add("mark-two");
elmnt.classList.add("mark");
this.state.scrolled = true;
this.markScrolledAsRead(this.state.scrolled_comment_id);
}

View File

@ -4,7 +4,7 @@ import { Subscription } from "rxjs";
import { retryWhen, delay, take } from 'rxjs/operators';
import { UserOperation, Post, Comment, CommunityUser, GetUserDetailsForm, SortType, UserDetailsResponse, UserView, CommentResponse, UserSettingsForm, LoginResponse, BanUserResponse, AddAdminResponse } from '../interfaces';
import { WebSocketService, UserService } from '../services';
import { msgOp, fetchLimit, routeSortTypeToEnum, capitalizeFirstLetter } from '../utils';
import { msgOp, fetchLimit, routeSortTypeToEnum, capitalizeFirstLetter, themes, setTheme } from '../utils';
import { PostListing } from './post-listing';
import { CommentNodes } from './comment-nodes';
import { MomentTime } from './moment-time';
@ -61,6 +61,7 @@ export class User extends Component<any, UserState> {
page: this.getPageFromProps(this.props),
userSettingsForm: {
show_nsfw: null,
theme: null,
auth: null,
},
userSettingsLoading: null,
@ -285,7 +286,18 @@ export class User extends Component<any, UserState> {
<div class="card-body">
<h5><T i18nKey="settings">#</T></h5>
<form onSubmit={linkEvent(this, this.handleUserSettingsSubmit)}>
<div class="form-group row">
<div class="form-group">
<div class="col-12">
<label><T i18nKey="theme">#</T></label>
<select value={this.state.userSettingsForm.theme} onChange={linkEvent(this, this.handleUserSettingsThemeChange)} class="ml-2 custom-select custom-select-sm w-auto">
<option disabled><T i18nKey="theme">#</T></option>
{themes.map(theme =>
<option value={theme}>{theme}</option>
)}
</select>
</div>
</div>
<div class="form-group">
<div class="col-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" checked={this.state.userSettingsForm.show_nsfw} onChange={linkEvent(this, this.handleUserSettingsShowNsfwChange)}/>
@ -309,20 +321,18 @@ export class User extends Component<any, UserState> {
moderates() {
return (
<div>
<div class="card border-secondary mb-3">
<div class="card-body">
{this.state.moderates.length > 0 &&
<div>
<h5><T i18nKey="moderates">#</T></h5>
<ul class="list-unstyled mb-0">
{this.state.moderates.map(community =>
<li><Link to={`/c/${community.community_name}`}>{community.community_name}</Link></li>
)}
</ul>
</div>
}
{this.state.moderates.length > 0 &&
<div class="card border-secondary mb-3">
<div class="card-body">
<h5><T i18nKey="moderates">#</T></h5>
<ul class="list-unstyled mb-0">
{this.state.moderates.map(community =>
<li><Link to={`/c/${community.community_name}`}>{community.community_name}</Link></li>
)}
</ul>
</div>
</div>
</div>
}
</div>
)
}
@ -410,6 +420,12 @@ export class User extends Component<any, UserState> {
i.setState(i.state);
}
handleUserSettingsThemeChange(i: User, event: any) {
i.state.userSettingsForm.theme = event.target.value;
setTheme(event.target.value);
i.setState(i.state);
}
handleUserSettingsSubmit(i: User, event: any) {
event.preventDefault();
i.state.userSettingsLoading = true;
@ -435,6 +451,7 @@ export class User extends Component<any, UserState> {
this.state.loading = false;
if (this.isCurrentUser) {
this.state.userSettingsForm.show_nsfw = UserService.Instance.user.show_nsfw;
this.state.userSettingsForm.theme = UserService.Instance.user.theme ? UserService.Instance.user.theme : 'darkly';
}
document.title = `/u/${this.state.user.name} - ${WebSocketService.Instance.site.name}`;
window.scrollTo(0,0);

File diff suppressed because one or more lines are too long

16
ui/src/index.html vendored
View File

@ -6,8 +6,24 @@
<meta name="Description" content="Lemmy">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Icons -->
<link rel="shortcut icon" type="image/svg+xml" href="/static/assets/favicon.svg" />
<link rel="apple-touch-icon" href="/static/assets/apple-touch-icon.png" />
<!-- Styles -->
<link rel="stylesheet" type="text/css" href="/static/assets/css/tribute.css" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/themes/litera.min.css" id="litera" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/themes/minty.min.css" id="minty" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/themes/solar.min.css" id="solar" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/themes/united.min.css" id="united" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/themes/cyborg.min.css" id="cyborg" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/themes/darkly.min.css" id="darkly" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/themes/journal.min.css" id="journal" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/themes/sketchy.min.css" id="sketchy" />
<link rel="stylesheet" type="text/css" href="/static/assets/css/main.css" />
<!-- Scripts -->
<script async src="/static/assets/libs/sortable/sortable.min.js"></script>
</head>

4
ui/src/index.tsx vendored
View File

@ -19,10 +19,6 @@ import { Sponsors } from './components/sponsors';
import { Symbols } from './components/symbols';
import { i18n } from './i18next';
import './css/tribute.css';
import './css/bootstrap.min.css';
import './css/main.css';
import { WebSocketService, UserService } from './services';
const container = document.getElementById('app');

View File

@ -23,6 +23,7 @@ export interface User {
iss: string;
username: string;
show_nsfw: boolean;
theme: string;
}
export interface UserView {
@ -381,6 +382,7 @@ export interface LoginResponse {
export interface UserSettingsForm {
show_nsfw: boolean;
theme: string;
auth: string;
}

View File

@ -1,5 +1,6 @@
import * as Cookies from 'js-cookie';
import { User, LoginResponse } from '../interfaces';
import { setTheme } from '../utils';
import * as jwt_decode from 'jwt-decode';
import { Subject } from 'rxjs';
@ -14,6 +15,7 @@ export class UserService {
if (jwt) {
this.setUser(jwt);
} else {
setTheme();
console.log('No JWT cookie found.');
}
}
@ -27,8 +29,9 @@ export class UserService {
public logout() {
this.user = undefined;
Cookies.remove("jwt");
console.log("Logged out.");
setTheme();
this.sub.next({user: undefined, unreadCount: 0});
console.log("Logged out.");
}
public get auth(): string {
@ -37,6 +40,7 @@ export class UserService {
private setUser(jwt: string) {
this.user = jwt_decode(jwt);
setTheme(this.user.theme);
this.sub.next({user: this.user, unreadCount: 0});
console.log(this.user);
}

View File

@ -129,6 +129,7 @@ export const en = {
modified: 'modified',
nsfw: 'NSFW',
show_nsfw: 'Show NSFW content',
theme: 'Theme',
sponsors: 'Sponsors',
sponsors_of_lemmy: 'Sponsors of Lemmy',
sponsor_message: 'Lemmy is free, <1>open-source</1> software, meaning no advertising, monetizing, or venture capital, ever. Your donations directly support full-time development of the project. Thank you to the following people:',

14
ui/src/utils.ts vendored
View File

@ -238,3 +238,17 @@ export function getMomentLanguage(): string {
}
return lang;
}
export const themes = ['litera', 'minty', 'solar', 'united', 'cyborg','darkly', 'journal', 'sketchy'];
export function setTheme(theme: string = 'darkly') {
for (var i=0; i < themes.length; i++) {
let styleSheet = document.getElementById(themes[i]);
if (themes[i] == theme) {
styleSheet.removeAttribute("disabled");
} else {
styleSheet.setAttribute("disabled", "disabled");
}
}
}

5
ui/yarn.lock vendored
View File

@ -381,6 +381,11 @@ body@^5.1.0:
raw-body "~1.1.0"
safe-json-parse "~1.0.1"
bootswatch@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/bootswatch/-/bootswatch-4.3.1.tgz#be54748b420a1962dbcf9782605aac092f842e38"
integrity sha512-kNdpo/TnhO++aic1IODLIe1V0lx6pXwHMpwXMacpANDnuVDtgU1MUgUbVMC3rSWm4UcbImfwPraNYgjKDT0BtA==
bowser@^2.0.0-beta.3:
version "2.6.1"
resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.6.1.tgz#196599588af6f0413449c79ab3bf7a5a1bb3384f"