forked from nutomic/lemmy
parent
62ae25f90d
commit
272ab3948c
|
@ -0,0 +1 @@
|
|||
alter table user_ drop column theme;
|
|
@ -0,0 +1 @@
|
|||
alter table user_ add column theme varchar(20) default 'darkly' not null;
|
|
@ -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) {
|
||||
|
|
|
@ -72,6 +72,7 @@ mod tests {
|
|||
banned: false,
|
||||
updated: None,
|
||||
show_nsfw: false,
|
||||
theme: "darkly".into(),
|
||||
};
|
||||
|
||||
let person = expected_user.person();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -254,6 +254,7 @@ table! {
|
|||
published -> Timestamp,
|
||||
updated -> Nullable<Timestamp>,
|
||||
show_nsfw -> Bool,
|
||||
theme -> Varchar,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
@ -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",
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,10 +321,9 @@ export class User extends Component<any, UserState> {
|
|||
moderates() {
|
||||
return (
|
||||
<div>
|
||||
{this.state.moderates.length > 0 &&
|
||||
<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 =>
|
||||
|
@ -320,10 +331,9 @@ export class User extends Component<any, UserState> {
|
|||
)}
|
||||
</ul>
|
||||
</div>
|
||||
</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
|
@ -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>
|
||||
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:',
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue