Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9be5804b3e | |||
| e1bd2eab75 | |||
| ac7a05b09a | |||
| 71e0a35e06 | |||
| c217e5e9b3 | |||
| 8ba0c17db5 | |||
| 4e43c676b4 | |||
| b834d1c282 | |||
| 506fe9955d | |||
| 02c528cae4 | |||
| 2a58835f92 |
@@ -226,6 +226,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- restore_env:
|
- restore_env:
|
||||||
cache: none
|
cache: none
|
||||||
|
- run: cargo build
|
||||||
- run: crowdin upload -b master
|
- run: crowdin upload -b master
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
|
|||||||
@@ -18,3 +18,4 @@ tags.*
|
|||||||
search_index
|
search_index
|
||||||
.buildconfig
|
.buildconfig
|
||||||
__pycache__
|
__pycache__
|
||||||
|
/.vscode/
|
||||||
|
|||||||
Generated
+1172
-1206
File diff suppressed because it is too large
Load Diff
@@ -192,6 +192,27 @@ p.error {
|
|||||||
|
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
footer.authors {
|
||||||
|
div {
|
||||||
|
float: left;
|
||||||
|
margin-right: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.likes { color: $red; }
|
||||||
|
.reshares { color: $primary; }
|
||||||
|
|
||||||
|
span.likes, span.resahres {
|
||||||
|
font-family: "Route159",serif;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg.feather {
|
||||||
|
width: 0.85em;
|
||||||
|
height: 0.85em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
margin: 20px;
|
margin: 20px;
|
||||||
}
|
}
|
||||||
@@ -469,93 +490,6 @@ figure {
|
|||||||
|
|
||||||
/// Small screens
|
/// Small screens
|
||||||
@media screen and (max-width: 600px) {
|
@media screen and (max-width: 600px) {
|
||||||
@keyframes menuOpening {
|
|
||||||
from {
|
|
||||||
transform: scaleX(0);
|
|
||||||
transform-origin: left;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: scaleX(1);
|
|
||||||
transform-origin: left;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body > header {
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
nav#menu {
|
|
||||||
display: inline-flex;
|
|
||||||
z-index: 21;
|
|
||||||
}
|
|
||||||
|
|
||||||
#content {
|
|
||||||
display: none;
|
|
||||||
appearance: none;
|
|
||||||
text-align: center;
|
|
||||||
z-index: 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body > header:focus-within #content, #content.show {
|
|
||||||
position: fixed;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
animation: 0.2s menuOpening;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
transform: skewX(-10deg);
|
|
||||||
top: 0;
|
|
||||||
left: -20%;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
z-index: -10;
|
|
||||||
|
|
||||||
background: $primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
> nav {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
|
|
||||||
a {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
margin: 0;
|
|
||||||
padding: 1rem 1.5rem;
|
|
||||||
color: $background;
|
|
||||||
font-size: 1.4em;
|
|
||||||
font-weight: 300;
|
|
||||||
|
|
||||||
&.title { font-size: 1.8em; }
|
|
||||||
|
|
||||||
> *:first-child { width: 3rem; }
|
|
||||||
> img:first-child { height: 3rem; }
|
|
||||||
> *:last-child { margin-left: 1rem; }
|
|
||||||
> nav hr {
|
|
||||||
display: block;
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
|
||||||
border: solid $background 0.1rem;
|
|
||||||
}
|
|
||||||
.mobile-label { display: initial; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main .article-meta {
|
main .article-meta {
|
||||||
> *, .comments {
|
> *, .comments {
|
||||||
margin: 0 5%;
|
margin: 0 5%;
|
||||||
|
|||||||
@@ -101,6 +101,96 @@ body > header {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Small screens
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
@keyframes menuOpening {
|
||||||
|
from {
|
||||||
|
transform: scaleX(0);
|
||||||
|
transform-origin: left;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: scaleX(1);
|
||||||
|
transform-origin: left;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body > header {
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
nav#menu {
|
||||||
|
display: inline-flex;
|
||||||
|
z-index: 21;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
display: none;
|
||||||
|
appearance: none;
|
||||||
|
text-align: center;
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body > header:focus-within #content, #content.show {
|
||||||
|
position: fixed;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
animation: 0.2s menuOpening;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
transform: skewX(-10deg);
|
||||||
|
top: 0;
|
||||||
|
left: -20%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
z-index: -10;
|
||||||
|
|
||||||
|
background: $primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
> nav {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0;
|
||||||
|
padding: 1rem 1.5rem;
|
||||||
|
color: $background;
|
||||||
|
font-size: 1.4em;
|
||||||
|
font-weight: 300;
|
||||||
|
|
||||||
|
&.title { font-size: 1.8em; }
|
||||||
|
|
||||||
|
> *:first-child { width: 3rem; }
|
||||||
|
> img:first-child { height: 3rem; }
|
||||||
|
> *:last-child { margin-left: 1rem; }
|
||||||
|
> nav hr {
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
border: solid $background 0.1rem;
|
||||||
|
}
|
||||||
|
.mobile-label { display: initial; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Only enable label animations on large screens */
|
/* Only enable label animations on large screens */
|
||||||
@media screen and (min-width: 600px) {
|
@media screen and (min-width: 600px) {
|
||||||
header nav a {
|
header nav a {
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ pub enum Role {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Queryable, Identifiable, Clone, Debug, AsChangeset)]
|
#[derive(Queryable, Identifiable, Clone, Debug, AsChangeset)]
|
||||||
|
#[changeset_options(treat_none_as_null = "true")]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub username: String,
|
pub username: String,
|
||||||
|
|||||||
+627
-478
File diff suppressed because it is too large
Load Diff
+627
-457
File diff suppressed because it is too large
Load Diff
+604
-470
File diff suppressed because it is too large
Load Diff
+692
-481
File diff suppressed because it is too large
Load Diff
+686
-474
File diff suppressed because it is too large
Load Diff
+557
-429
File diff suppressed because it is too large
Load Diff
+570
-441
File diff suppressed because it is too large
Load Diff
+641
-481
File diff suppressed because it is too large
Load Diff
+697
-475
File diff suppressed because it is too large
Load Diff
+688
-484
File diff suppressed because it is too large
Load Diff
+615
-474
File diff suppressed because it is too large
Load Diff
+567
-436
File diff suppressed because it is too large
Load Diff
+688
-474
File diff suppressed because it is too large
Load Diff
+663
-457
File diff suppressed because it is too large
Load Diff
+641
-525
File diff suppressed because it is too large
Load Diff
+695
-481
File diff suppressed because it is too large
Load Diff
+477
-408
File diff suppressed because it is too large
Load Diff
+690
-484
File diff suppressed because it is too large
Load Diff
+579
-446
File diff suppressed because it is too large
Load Diff
+598
-461
File diff suppressed because it is too large
Load Diff
+697
-481
File diff suppressed because it is too large
Load Diff
+561
-432
File diff suppressed because it is too large
Load Diff
+569
-438
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -24,9 +24,9 @@ if [ $ARCH == "aarch64" -o $ARCH == "armv71" ] ; then
|
|||||||
apt-get install -y --no-install-recommends build-essential subversion ninja-build cmake
|
apt-get install -y --no-install-recommends build-essential subversion ninja-build cmake
|
||||||
mkdir -p /scratch/src
|
mkdir -p /scratch/src
|
||||||
cd /scratch/src
|
cd /scratch/src
|
||||||
svn co http://llvm.org/svn/llvm-project/llvm/tags/RELEASE_800/final/ llvm
|
svn co http://llvm.org/svn/llvm-project/llvm/tags/RELEASE_900/final/ llvm
|
||||||
cd /scratch/src/llvm/tools
|
cd /scratch/src/llvm/tools
|
||||||
svn co http://llvm.org/svn/llvm-project/lld/tags/RELEASE_800/final/ lld
|
svn co http://llvm.org/svn/llvm-project/lld/tags/RELEASE_900/final/ lld
|
||||||
mkdir -p /scratch/build/arm
|
mkdir -p /scratch/build/arm
|
||||||
cd /scratch/build/arm
|
cd /scratch/build/arm
|
||||||
if [ "$ARCH" == "aarch64" ] ; then
|
if [ "$ARCH" == "aarch64" ] ; then
|
||||||
|
|||||||
+4
-3
@@ -8,7 +8,7 @@ description: |
|
|||||||
* Media management: you can upload pictures to illustrate your articles, but also audio files if you host a podcast, and manage them all from Plume.
|
* Media management: you can upload pictures to illustrate your articles, but also audio files if you host a podcast, and manage them all from Plume.
|
||||||
* Federation: Plume is part of a network of interconnected websites called the Fediverse. Each of these websites (often called instances) have their own rules and thematics, but they can all communicate with each other.
|
* Federation: Plume is part of a network of interconnected websites called the Fediverse. Each of these websites (often called instances) have their own rules and thematics, but they can all communicate with each other.
|
||||||
* Collaborative writing: invite other people to your blogs, and write articles together.
|
* Collaborative writing: invite other people to your blogs, and write articles together.
|
||||||
grade: devel # must be 'stable' to release into candidate/stable channels
|
grade: stable
|
||||||
confinement: strict
|
confinement: strict
|
||||||
|
|
||||||
apps:
|
apps:
|
||||||
@@ -25,12 +25,13 @@ parts:
|
|||||||
plume:
|
plume:
|
||||||
plugin: rust
|
plugin: rust
|
||||||
source: .
|
source: .
|
||||||
rust-revision: nightly-2019-03-23
|
rust-revision: nightly-2020-01-15
|
||||||
build-packages:
|
build-packages:
|
||||||
- libssl-dev
|
- libssl-dev
|
||||||
- pkg-config
|
- pkg-config
|
||||||
- libsqlite3-dev
|
- libsqlite3-dev
|
||||||
- gettext
|
- gettext
|
||||||
|
- libclang-8-dev
|
||||||
- on arm64,armhf,ppc64el,s390x:
|
- on arm64,armhf,ppc64el,s390x:
|
||||||
- lld-8
|
- lld-8
|
||||||
override-build: |
|
override-build: |
|
||||||
@@ -42,7 +43,7 @@ parts:
|
|||||||
# Only Tier 1 Rust platforms get rust-lld
|
# Only Tier 1 Rust platforms get rust-lld
|
||||||
# On the others (arm64, armhf, powerpc64, s390x) fall back to using
|
# On the others (arm64, armhf, powerpc64, s390x) fall back to using
|
||||||
# the system LLD we've installed earlier.
|
# the system LLD we've installed earlier.
|
||||||
case ${SNAPCRAFT_ARCH_TRIPLE} in \
|
case ${SNAPCRAFT_ARCH_TRIPLET} in \
|
||||||
aarch64-linux-gnu|arm-linux-gnueabihf|powerpc64-linux-gnu|s390x-linux-gnu) \
|
aarch64-linux-gnu|arm-linux-gnueabihf|powerpc64-linux-gnu|s390x-linux-gnu) \
|
||||||
RUSTFLAGS="-C linker=lld-8" cargo web deploy -p plume-front --release \
|
RUSTFLAGS="-C linker=lld-8" cargo web deploy -p plume-front --release \
|
||||||
;; \
|
;; \
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use lettre::Transport;
|
|||||||
use rocket::http::ext::IntoOwned;
|
use rocket::http::ext::IntoOwned;
|
||||||
use rocket::{
|
use rocket::{
|
||||||
http::{uri::Uri, Cookie, Cookies, SameSite},
|
http::{uri::Uri, Cookie, Cookies, SameSite},
|
||||||
request::{Form, LenientForm},
|
request::LenientForm,
|
||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
State,
|
State,
|
||||||
};
|
};
|
||||||
@@ -159,7 +159,7 @@ pub struct ResetForm {
|
|||||||
#[post("/password-reset", data = "<form>")]
|
#[post("/password-reset", data = "<form>")]
|
||||||
pub fn password_reset_request(
|
pub fn password_reset_request(
|
||||||
mail: State<'_, Arc<Mutex<Mailer>>>,
|
mail: State<'_, Arc<Mutex<Mailer>>>,
|
||||||
form: Form<ResetForm>,
|
form: LenientForm<ResetForm>,
|
||||||
rockets: PlumeRocket,
|
rockets: PlumeRocket,
|
||||||
) -> Ructe {
|
) -> Ructe {
|
||||||
if User::find_by_email(&*rockets.conn, &form.email).is_ok() {
|
if User::find_by_email(&*rockets.conn, &form.email).is_ok() {
|
||||||
@@ -216,7 +216,7 @@ fn passwords_match(form: &NewPasswordForm) -> Result<(), ValidationError> {
|
|||||||
#[post("/password-reset/<token>", data = "<form>")]
|
#[post("/password-reset/<token>", data = "<form>")]
|
||||||
pub fn password_reset(
|
pub fn password_reset(
|
||||||
token: String,
|
token: String,
|
||||||
form: Form<NewPasswordForm>,
|
form: LenientForm<NewPasswordForm>,
|
||||||
rockets: PlumeRocket,
|
rockets: PlumeRocket,
|
||||||
) -> Result<Flash<Redirect>, Ructe> {
|
) -> Result<Flash<Redirect>, Ructe> {
|
||||||
form.validate()
|
form.validate()
|
||||||
|
|||||||
+4
-1
@@ -399,7 +399,10 @@ pub fn update(
|
|||||||
)
|
)
|
||||||
.0,
|
.0,
|
||||||
);
|
);
|
||||||
user.preferred_theme = form.theme.clone();
|
user.preferred_theme = form
|
||||||
|
.theme
|
||||||
|
.clone()
|
||||||
|
.and_then(|t| if &t == "" { None } else { Some(t) });
|
||||||
user.hide_custom_css = form.hide_custom_css;
|
user.hide_custom_css = form.hide_custom_css;
|
||||||
let _: User = user.save_changes(&*conn).map_err(Error::from)?;
|
let _: User = user.save_changes(&*conn).map_err(Error::from)?;
|
||||||
|
|
||||||
|
|||||||
@@ -32,9 +32,9 @@
|
|||||||
<form method="post" action="@uri!(instance::delete_email_blocklist)">
|
<form method="post" action="@uri!(instance::delete_email_blocklist)">
|
||||||
<header>
|
<header>
|
||||||
@if emails.is_empty() {
|
@if emails.is_empty() {
|
||||||
<input type="submit" class="destructive" value='@i18n!(ctx.1, "Delete selected emails")'>
|
|
||||||
} else {
|
|
||||||
<p class="center" >@i18n!(ctx.1, "There are no blocked emails on your instance")</p>
|
<p class="center" >@i18n!(ctx.1, "There are no blocked emails on your instance")</p>
|
||||||
|
} else {
|
||||||
|
<input type="submit" class="destructive" value='@i18n!(ctx.1, "Delete selected emails")'>
|
||||||
}
|
}
|
||||||
</header>
|
</header>
|
||||||
<div class="list">
|
<div class="list">
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
<p class="p-summary" dir="auto">@article.subtitle</p>
|
<p class="p-summary" dir="auto">@article.subtitle</p>
|
||||||
</main>
|
</main>
|
||||||
<footer class="authors">
|
<footer class="authors">
|
||||||
|
<div>
|
||||||
@Html(i18n!(ctx.1, "By {0}"; format!(
|
@Html(i18n!(ctx.1, "By {0}"; format!(
|
||||||
"<a class=\"p-author h-card\" href=\"{}\">{}</a>",
|
"<a class=\"p-author h-card\" href=\"{}\">{}</a>",
|
||||||
uri!(user::details: name = &article.get_authors(ctx.0).unwrap_or_default()[0].fqn),
|
uri!(user::details: name = &article.get_authors(ctx.0).unwrap_or_default()[0].fqn),
|
||||||
@@ -26,8 +27,20 @@
|
|||||||
⋅ <span class="dt-published" datetime="@article.creation_date.format("%F %T")">@article.creation_date.format("%B %e, %Y")</span>
|
⋅ <span class="dt-published" datetime="@article.creation_date.format("%F %T")">@article.creation_date.format("%B %e, %Y")</span>
|
||||||
}
|
}
|
||||||
⋅ <a href="@uri!(blogs::details: name = &article.get_blog(ctx.0).unwrap().fqn, page = _)">@article.get_blog(ctx.0).unwrap().title</a>
|
⋅ <a href="@uri!(blogs::details: name = &article.get_blog(ctx.0).unwrap().fqn, page = _)">@article.get_blog(ctx.0).unwrap().title</a>
|
||||||
|
⋅
|
||||||
|
</div>
|
||||||
@if !article.published {
|
@if !article.published {
|
||||||
⋅ @i18n!(ctx.1, "Draft")
|
<div>⋅ @i18n!(ctx.1, "Draft")</div>
|
||||||
|
} else {
|
||||||
|
<div>
|
||||||
|
<span class="likes" aria-label="@i18n!(ctx.1, "One like", "{0} likes"; article.count_likes(ctx.0).unwrap_or_default())" title="@i18n!(ctx.1, "One like", "{0} likes"; article.count_likes(ctx.0).unwrap_or_default())">
|
||||||
|
@icon!("heart") @article.count_likes(ctx.0).unwrap_or_default()
|
||||||
|
</span>
|
||||||
|
⋅
|
||||||
|
<span class="reshares" aria-label="@i18n!(ctx.1, "One like", "{0} boost"; article.count_reshares(ctx.0).unwrap_or_default())" title="@i18n!(ctx.1, "One boost", "{0} boosts"; article.count_reshares(ctx.0).unwrap_or_default())">
|
||||||
|
@icon!("repeat") @article.count_reshares(ctx.0).unwrap_or_default()
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
.default(login_form.password)
|
.default(login_form.password)
|
||||||
.error(&login_errs)
|
.error(&login_errs)
|
||||||
.set_prop("minlength", 1)
|
.set_prop("minlength", 1)
|
||||||
|
.input_type("password")
|
||||||
.html(ctx.1))
|
.html(ctx.1))
|
||||||
<input type="submit" value="@i18n!(ctx.1, "Log in")" />
|
<input type="submit" value="@i18n!(ctx.1, "Log in")" />
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
Reference in New Issue
Block a user