mirror of
http://git.carcosa.net/jmcbray/brutaldon.git
synced 2024-11-27 09:10:08 -05:00
Add theme support and move preferences into the database
Squashed commit of the following: commit be4e1ab286f54caa6f44367d2de3cf9e6cb69e68 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Tue Aug 28 12:03:17 2018 -0400 Set timezone in session as early as possible commit f1c03349c40ca1aca7f77c32333ee83585495626 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Tue Aug 28 10:06:18 2018 -0400 Don't hide all .is-hidden in brutalist themes commit f35a6c5600b091fe0ec4ad78eb5f1a02a4945a65 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Tue Aug 28 09:44:10 2018 -0400 Rename vt240don.css to vt240don-amber.css commit 074478937af309d10ff2d7f8f482dbff20ac7cf9 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Tue Aug 28 09:41:43 2018 -0400 Tweak vt240 amber theme and add vt240 green theme commit b205cfe7376d067799863d7db1ce3c4530b0ba74 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Tue Aug 28 08:39:11 2018 -0400 Remove caching of Mastodon connections There's not a good way of invalidating them, and they've started causing timeouts in this branch. commit c24a697a39173ff23391220fabad0dc6605cb5ef Author: Jason McBrayer <jmcbray@carcosa.net> Date: Mon Aug 27 14:46:21 2018 -0400 Make minimal-large a little less bare commit 6fee850cf6ba1edb573a7fedf43af3a343410c9b Author: Jason McBrayer <jmcbray@carcosa.net> Date: Mon Aug 27 14:24:57 2018 -0400 Add minimal-large theme commit b345dedbfcf55c3142d07a6f5320c677cfb534f0 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Mon Aug 27 13:19:51 2018 -0400 Add vt240don style by @enkiv2 commit f013ff235663ee21f2d0962a019ce7bc3c80f7b0 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Mon Aug 27 09:15:51 2018 -0400 Fix crash in search commit 76c4134e9ddebbdf8a8dccab79361e71438877e6 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Mon Aug 27 08:35:02 2018 -0400 Fix crash in oauth_callback commit d725018d6a34544ac8c92deac27502c457d4d3c8 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Mon Aug 27 08:31:19 2018 -0400 Fix crash in oauth_callback commit 830264359dbdbf7c34e1d1ae715cb68016cd47f4 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Mon Aug 27 08:28:17 2018 -0400 Fix crash in oauth_callback commit 2a525298995d108a290484786a7493bfb99af2c8 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Mon Aug 27 08:27:03 2018 -0400 Fix crash in oauth_callback commit d43eb63146eb21a283290287b9db4d518f36435e Author: Jason McBrayer <jmcbray@carcosa.net> Date: Mon Aug 27 08:25:27 2018 -0400 Fix crash in oauth_callback commit ae9a58a0ae010fdc12a7498d691b7b8f8da95e03 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Mon Aug 27 08:12:19 2018 -0400 Fix up default values for default themes again commit a8fde1710b4d23f2bdd0ced4eeffd44b4e80b756 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Mon Aug 27 08:11:18 2018 -0400 Fixes for dark theme commit c4a7501cf263afbdc6bf65623e9c8dc5f03f40f7 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Mon Aug 27 08:11:04 2018 -0400 Small fix in full toot view commit 69caeea0010e7d59106fba780744592ed9145f61 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Sun Aug 26 22:50:53 2018 -0400 Fix up settings display, navbar, typo in links commit 0e24a394eabe78d8cba864beaedb03a42f916a20 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Sun Aug 26 22:36:58 2018 -0400 Fix default theme paths commit aca5c53561cd8647d42244fd51720e146fddbf94 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Sun Aug 26 22:35:33 2018 -0400 More themes prep commit 6921c55a41db14e155b5ed62c48e3e67d8626b13 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Sun Aug 26 21:42:53 2018 -0400 Actually load themes commit 134952ff17e3a8672e21175395282d91f48f1d2b Author: Jason McBrayer <jmcbray@carcosa.net> Date: Sun Aug 26 21:34:06 2018 -0400 Base and fullbrutalism themes work, but only coincidentally commit 658aca52955507eda007165e9c44031d417e0076 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Sun Aug 26 19:47:48 2018 -0400 Make filtering preference work again commit 90267055b5a2fc51337b0a3e34b3a5643088e17f Author: Jason McBrayer <jmcbray@carcosa.net> Date: Sun Aug 26 19:34:47 2018 -0400 Fix up settings view, form, and model commit d58769ecdffad239cc8aa37ebca9c2e87372ebd0 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Sun Aug 26 19:12:06 2018 -0400 Fix up old_login to work with new preferences system commit d8b084a379894a3a40c3eed1c87465f7c77ad7eb Author: Jason McBrayer <jmcbray@carcosa.net> Date: Sun Aug 26 18:11:03 2018 -0400 Update settings view to use preferences system commit 49471ae97131bdb0d8152411afdf1987d6c64652 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Sat Aug 25 10:53:04 2018 -0400 Update login logic to match new account models, simplify. Not tested yet. commit 57cce7c0f45fe07dd522a61c9e056db982455843 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Sat Aug 25 10:18:53 2018 -0400 Fix up models and forms to meet current needs commit 0634c038ee9220164662d1e933a2f1c83e5af70d Author: Jason McBrayer <jmcbray@carcosa.net> Date: Fri Aug 24 22:42:07 2018 -0400 Update fields in models for settings branch commit 510509e28254cb3ee38b70538d1c0b788448d624 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Fri Jun 22 08:39:42 2018 -0400 Update settings view a bit; still in progress commit 5a91a57ceb1d737ed371bd6800ddf6ea0a917a8f Author: Jason McBrayer <jmcbray@carcosa.net> Date: Tue Jun 19 06:27:19 2018 -0400 Add forms object for new preferences commit af4883c172d2b66d83c55b00cee1490fa88ddd4f Author: Jason McBrayer <jmcbray@carcosa.net> Date: Tue Jun 19 06:26:35 2018 -0400 Make sure newly created accounts have preferences attached commit f0ae97b2bf8735bd5c369f273fb51d74deb05450 Author: Jason McBrayer <jmcbray@carcosa.net> Date: Mon Jun 18 21:33:41 2018 -0400 Setup for themes and related options
This commit is contained in:
parent
db1ed32490
commit
5bdb2de646
1
.gitignore
vendored
1
.gitignore
vendored
@ -110,3 +110,4 @@ pip-selfcheck.json
|
||||
/Pipfile.lock
|
||||
/dev_https
|
||||
node_modules
|
||||
/TAGS
|
||||
|
@ -1,6 +1,8 @@
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from pytz import common_timezones
|
||||
from .models import Theme, Preference
|
||||
|
||||
|
||||
PRIVACY_CHOICES = (('public', 'Public'),
|
||||
('unlisted', 'Unlisted'),
|
||||
@ -14,36 +16,17 @@ MAX_LENGTH = settings.TOOT_MAX_LENGTH
|
||||
class LoginForm(forms.Form):
|
||||
instance = forms.CharField(label="Instance",
|
||||
max_length=256)
|
||||
username = forms.CharField(label="Email",
|
||||
max_length=256)
|
||||
email = forms.EmailField(label="Email")
|
||||
password = forms.CharField(widget=forms.PasswordInput())
|
||||
|
||||
class OAuthLoginForm(forms.Form):
|
||||
instance = forms.CharField(label="Instance",
|
||||
max_length=256)
|
||||
|
||||
class SettingsForm(forms.Form):
|
||||
fullbrutalism = forms.BooleanField(label="Use FULLBRUTALISM mode?",
|
||||
required=False,
|
||||
help_text=
|
||||
"""FULLBRUTALISM mode strips away most of the niceties of modern web design when
|
||||
brutaldon is viewed in a graphical browser. It has no effect in text-only browsers.""")
|
||||
filter_replies = forms.BooleanField(label="Filter replies from home timeline?",
|
||||
required=False,
|
||||
help_text=
|
||||
"""Should replies be filtered out of your home timeline, giving you only pure,
|
||||
top-level posts?""")
|
||||
filter_boosts = forms.BooleanField(label="Filter boosts from home timeline?",
|
||||
required=False,
|
||||
help_text=
|
||||
"""Should replies be filtered out of your home timeline, giving you only pure,
|
||||
Original Content?""")
|
||||
timezone = forms.ChoiceField(label="Your local timezone",
|
||||
choices=timezones,
|
||||
required=False,
|
||||
help_text=
|
||||
"""What time zone do you prefer to have times displayed in? The default choice is UTC.""")
|
||||
|
||||
class PreferencesForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Preference
|
||||
fields = ['theme', 'filter_replies', 'filter_boosts', 'timezone']
|
||||
|
||||
class PostForm(forms.Form):
|
||||
"""def status_post(self, status, in_reply_to_id=None, media_ids=None,
|
||||
|
42
brutaldon/migrations/0005_auto_20180618_2103.py
Normal file
42
brutaldon/migrations/0005_auto_20180618_2103.py
Normal file
@ -0,0 +1,42 @@
|
||||
# Generated by Django 2.0.6 on 2018-06-19 01:03
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('brutaldon', '0004_auto_20180424_1424'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Preference',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('data_saver', models.BooleanField(default=False)),
|
||||
('fix_emojos', models.BooleanField(default=False)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Theme',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.TextField(max_length=80)),
|
||||
('main_css', models.TextField(max_length=1024)),
|
||||
('tweaks_css', models.TextField(blank=True, max_length=1024, null=True)),
|
||||
('is_brutalist', models.BooleanField(default=False)),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='preference',
|
||||
name='theme',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='brutaldon.Theme'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='account',
|
||||
name='preferences',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='brutaldon.Preference'),
|
||||
),
|
||||
]
|
18
brutaldon/migrations/0006_auto_20180618_2112.py
Normal file
18
brutaldon/migrations/0006_auto_20180618_2112.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.0.6 on 2018-06-19 01:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('brutaldon', '0005_auto_20180618_2103'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='theme',
|
||||
name='main_css',
|
||||
field=models.TextField(blank=True, default='css/fullbrutalism.css', max_length=1024, null=True),
|
||||
),
|
||||
]
|
47
brutaldon/migrations/0007_auto_20180618_2115.py
Normal file
47
brutaldon/migrations/0007_auto_20180618_2115.py
Normal file
@ -0,0 +1,47 @@
|
||||
# Generated by Django 2.0.6 on 2018-06-19 01:03
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
def set_up_default_themes(apps, schema_editor):
|
||||
Theme = apps.get_model('brutaldon', 'Theme')
|
||||
default = Theme(name="default",
|
||||
main_css="css/bulma.min.css",
|
||||
tweaks_css="css/brutaldon.css",
|
||||
is_brutalist=False)
|
||||
default.save()
|
||||
dark = Theme(name="default dark",
|
||||
main_css="css/bulmaswatch-darkly.min.css",
|
||||
tweaks_css="css/brutaldon-dark.css",
|
||||
is_brutalist=False)
|
||||
dark.save()
|
||||
brutalism = Theme(name="FULLBRUTALISM",
|
||||
main_css="css/fullbrutalism.css",
|
||||
is_brutalist=True)
|
||||
brutalism.save()
|
||||
large = Theme(name="Minimalist Large", main_css="css/minimal-large.css",
|
||||
is_brutalist=True)
|
||||
large.save()
|
||||
vt240 = Theme(name="vt240 amber", main_css="css/vt240don-amber.css",
|
||||
is_brutalist=True)
|
||||
vt240.save()
|
||||
vt240_green = Theme(name="vt240 green", main_css="css/vt240don-green.css",
|
||||
is_brutalist=True)
|
||||
vt240_green.save()
|
||||
minimal = Theme(name="No styling at all", main_css=None, is_brutalist=True)
|
||||
minimal.save()
|
||||
|
||||
def delete_themes(apps, schema_editor):
|
||||
Theme = apps.get_model('brutaldon' 'Theme')
|
||||
for theme in Theme.objects.all():
|
||||
theme.delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('brutaldon', '0006_auto_20180618_2112'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(set_up_default_themes, delete_themes)
|
||||
]
|
18
brutaldon/migrations/0008_auto_20180618_2140.py
Normal file
18
brutaldon/migrations/0008_auto_20180618_2140.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.0.6 on 2018-06-19 01:40
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('brutaldon', '0007_auto_20180618_2115'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='theme',
|
||||
name='name',
|
||||
field=models.TextField(max_length=80, unique=True),
|
||||
),
|
||||
]
|
46
brutaldon/migrations/0009_auto_20180824_2241.py
Normal file
46
brutaldon/migrations/0009_auto_20180824_2241.py
Normal file
File diff suppressed because one or more lines are too long
58
brutaldon/migrations/0010_auto_20180825_1009.py
Normal file
58
brutaldon/migrations/0010_auto_20180825_1009.py
Normal file
File diff suppressed because one or more lines are too long
18
brutaldon/migrations/0011_auto_20180825_1017.py
Normal file
18
brutaldon/migrations/0011_auto_20180825_1017.py
Normal file
File diff suppressed because one or more lines are too long
18
brutaldon/migrations/0012_auto_20180826_1853.py
Normal file
18
brutaldon/migrations/0012_auto_20180826_1853.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.1 on 2018-08-26 22:53
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('brutaldon', '0011_auto_20180825_1017'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='account',
|
||||
name='username',
|
||||
field=models.EmailField(max_length=254, unique=True),
|
||||
),
|
||||
]
|
19
brutaldon/migrations/0013_auto_20180826_1935.py
Normal file
19
brutaldon/migrations/0013_auto_20180826_1935.py
Normal file
@ -0,0 +1,19 @@
|
||||
# Generated by Django 2.1 on 2018-08-26 23:35
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('brutaldon', '0012_auto_20180826_1853'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='preference',
|
||||
name='theme',
|
||||
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='brutaldon.Theme'),
|
||||
),
|
||||
]
|
@ -1,17 +1,41 @@
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from pytz import common_timezones
|
||||
|
||||
timezones = [(tz, tz) for tz in common_timezones]
|
||||
|
||||
class Client(models.Model):
|
||||
name = models.TextField(default = "brutaldon")
|
||||
name = models.CharField(default = "brutaldon", max_length=80)
|
||||
api_base_id = models.URLField(default="https://mastodon.social")
|
||||
client_id = models.TextField(null=True, blank=True)
|
||||
client_secret = models.TextField(null=True, blank=True)
|
||||
client_id = models.CharField(null=True, blank=True, max_length=2048)
|
||||
client_secret = models.CharField(null=True, blank=True, max_length=2048)
|
||||
|
||||
def __str__(self):
|
||||
return self.name + ": " + self.api_base_id
|
||||
|
||||
class Theme(models.Model):
|
||||
name = models.CharField(max_length=80, unique=True)
|
||||
prefix = models.CharField(max_length=40, null=True, default="default")
|
||||
main_css = models.CharField(max_length=1024, blank=True, null=True,
|
||||
default="css/fullbrutalism.css")
|
||||
tweaks_css = models.CharField(max_length=1024, blank=True, null=True)
|
||||
is_brutalist = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Preference(models.Model):
|
||||
theme = models.ForeignKey(Theme, models.CASCADE, null=False, default=1)
|
||||
filter_replies = models.BooleanField(default=False)
|
||||
filter_boosts = models.BooleanField(default=False)
|
||||
timezone = models.CharField(max_length=80, blank=True, null=True,
|
||||
choices=timezones, default='UTC')
|
||||
|
||||
class Account(models.Model):
|
||||
username = models.EmailField()
|
||||
username = models.EmailField(unique=True)
|
||||
email = models.EmailField(null=True, blank=True)
|
||||
django_user = models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE, null=True)
|
||||
access_token = models.TextField(null=True, blank=True)
|
||||
access_token = models.CharField(null=True, blank=True, max_length=2048)
|
||||
client= models.ForeignKey(Client, models.SET_NULL, null=True)
|
||||
preferences = models.ForeignKey(Preference, models.SET_NULL, null=True)
|
||||
|
||||
|
109
brutaldon/static/css/brutaldon-dark.css
Normal file
109
brutaldon/static/css/brutaldon-dark.css
Normal file
@ -0,0 +1,109 @@
|
||||
body.has-navbar-fixed-top {
|
||||
padding-top: 48px;
|
||||
}
|
||||
|
||||
body > section > div.container {
|
||||
max-width: 90ex;
|
||||
}
|
||||
|
||||
|
||||
.reblog-icon {
|
||||
position: relative;
|
||||
top: -24px;
|
||||
left: 40px;
|
||||
}
|
||||
|
||||
img.fav-avatar {
|
||||
display: inline;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.media {
|
||||
border-radius: 5px;
|
||||
-webkit-box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1);
|
||||
box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1);
|
||||
padding: 1.25rem;
|
||||
margin-bottom: 0.75rem;
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
.media-content {
|
||||
padding: 1.5ex;
|
||||
}
|
||||
|
||||
.is-max-128 {
|
||||
max-height: 128px;
|
||||
max-width: 128px;
|
||||
}
|
||||
|
||||
.is-max-256 {
|
||||
max-height: 256px;
|
||||
max-width: 256px;
|
||||
}
|
||||
|
||||
figure.media-left p.image a img
|
||||
{
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
img.avatar
|
||||
{
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.active-context {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
h2.subtitle
|
||||
{
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
article.media.user-info .content img
|
||||
{
|
||||
max-height: 1.5rem;
|
||||
max-width: 1.5rem;
|
||||
}
|
||||
|
||||
span.account-locked
|
||||
{
|
||||
margin-top: 48px;
|
||||
margin-left: -16px;
|
||||
}
|
||||
|
||||
.errorlist
|
||||
{
|
||||
color: #FF0000;
|
||||
}
|
||||
|
||||
.emoji-box
|
||||
{
|
||||
padding: .75rem;
|
||||
background-color: #444;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
img.emoji
|
||||
{
|
||||
display: inline;
|
||||
max-height: 1.5em;
|
||||
max-width: 1.5em;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
emoji-link
|
||||
{
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.media {
|
||||
display: block;
|
||||
}
|
||||
}
|
6
brutaldon/static/css/bulmaswatch-materia.min.css
vendored
Normal file
6
brutaldon/static/css/bulmaswatch-materia.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
230
brutaldon/static/css/minimal-large.css
Normal file
230
brutaldon/static/css/minimal-large.css
Normal file
@ -0,0 +1,230 @@
|
||||
body, input, textarea, select {
|
||||
font-family: sans-serif;
|
||||
background-color: #FAFAFA;
|
||||
color: #000;
|
||||
margin: 1em;
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
input[text], textarea
|
||||
{
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 120em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: blue;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:active {
|
||||
color: red;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: purple;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
img, img.is-32x32 {
|
||||
float: left;
|
||||
max-width: 512px;
|
||||
max-height: auto;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1024px) {
|
||||
.container {
|
||||
max-width: 960px;
|
||||
width: 960px;
|
||||
}
|
||||
.container.is-fluid {
|
||||
margin-left: 64px;
|
||||
margin-right: 64px;
|
||||
max-width: none;
|
||||
width: auto;
|
||||
}
|
||||
.navbar,
|
||||
.navbar-menu,
|
||||
.navbar-start,
|
||||
.navbar-end {
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
}
|
||||
.navbar-start {
|
||||
justify-content: flex-start;
|
||||
margin-right: auto;
|
||||
}
|
||||
.navbar-end {
|
||||
justify-content: flex-end;
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1279px) {
|
||||
.container.is-widescreen {
|
||||
max-width: 1152px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1471px) {
|
||||
.container.is-fullhd {
|
||||
max-width: 1344px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1280px) {
|
||||
.container {
|
||||
max-width: 1152px;
|
||||
width: 1152px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1472px) {
|
||||
.container {
|
||||
max-width: 1344px;
|
||||
width: 1344px;
|
||||
}
|
||||
}
|
||||
|
||||
body > section > div.container {
|
||||
max-width: 90ex;
|
||||
}
|
||||
|
||||
.level {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 3ex;
|
||||
font-weight: bold;
|
||||
margin-top: 1ex;
|
||||
margin-bottom: 1ex;
|
||||
}
|
||||
.subtitle {
|
||||
font-size: 1.5ex;
|
||||
font-weight: bold;
|
||||
margin-top: 0.25ex;
|
||||
margin-bottom: 0.25ex;
|
||||
}
|
||||
.toot {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.image.is-32x32, .is-32x32 img, img.is-32x32 {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.image.is-48x48, .is-48x48 img, img.is-48x48 {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.image.is-64x64, .is-64x64 img, img.is-64x64 {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.image.is-96x96, .is-96x96 img, img.is-96x96 {
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
}
|
||||
|
||||
.is-max-128 {
|
||||
max-height: 128px;
|
||||
max-width: 128px;
|
||||
}
|
||||
|
||||
.is-max-256 {
|
||||
max-height: 256px;
|
||||
max-width: 256px;
|
||||
}
|
||||
|
||||
.media {
|
||||
padding: 1ex;
|
||||
margin: 4px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.media.active-context {
|
||||
background-color: #DDD;
|
||||
}
|
||||
|
||||
|
||||
.field
|
||||
{
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
label
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.control, .select
|
||||
{
|
||||
margin-top: 0.5ex;
|
||||
margin-bottom: 0.5ex;
|
||||
}
|
||||
|
||||
.account-avatar
|
||||
{
|
||||
display: inline-block;
|
||||
}
|
||||
.reblog-icon
|
||||
{
|
||||
margin-top: 32px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.media-content
|
||||
{
|
||||
margin-top: 1ex;
|
||||
}
|
||||
|
||||
.media-content > div > p
|
||||
{
|
||||
margin-bottom: 1ex;
|
||||
}
|
||||
|
||||
.textarea
|
||||
{
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.errorlist
|
||||
{
|
||||
color: #FF0000;
|
||||
}
|
||||
|
||||
img.emoji
|
||||
{
|
||||
display: inline;
|
||||
max-height: 1.5rem;
|
||||
max-width: 1.5rem;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
hr.is-hidden
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.box
|
||||
{
|
||||
border-radius: 5px;
|
||||
border: 1px solid #000;
|
||||
padding: 1.5em;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
184
brutaldon/static/css/vt240don-amber.css
Normal file
184
brutaldon/static/css/vt240don-amber.css
Normal file
@ -0,0 +1,184 @@
|
||||
html, a, div, div.notification, body, body div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header, menu, nav, section, time, mark, audio, video, details, summary, h1.title, h2.subtitle {
|
||||
font-family: "monospace";
|
||||
color: #ff7700;
|
||||
background-color: #000000;
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
|
||||
tr, td, ul, ol {
|
||||
border-color: #ff7700;
|
||||
outline: 1px solid #ff7700;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
a, a.button, a.button.is-primary, input.button.is-primary, input, .input, .textarea, .footer, .label, select, textarea {
|
||||
color: #ff8800;
|
||||
border-color: #ff8800;
|
||||
background-color: #000000;
|
||||
font-weight: bolder;
|
||||
text-decoration-line: none;
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
|
||||
a:hover, a.button:hover, a.button.is-primary:hover, input.button.is-primary:hover {
|
||||
color: #000000;
|
||||
background-color: #ff8800;
|
||||
}
|
||||
|
||||
.control input[type=text], .control textarea
|
||||
{
|
||||
width: 100%;
|
||||
max-width: 80em;
|
||||
border: 1px solid #ff7700;
|
||||
margin-bottom: 1ex;
|
||||
}
|
||||
|
||||
.control input, .control select
|
||||
{
|
||||
border: 1px solid #ff7700;
|
||||
background-color: #000000;
|
||||
margin-bottom: 1ex;
|
||||
}
|
||||
|
||||
img {
|
||||
filter: grayscale(100%);
|
||||
-webkit-filter: grayscale(100%);
|
||||
}
|
||||
|
||||
|
||||
div.card-header-title, div.card-header-icon {
|
||||
color: #ff7700;
|
||||
-webkit-text-stroke: 2px black;
|
||||
-moz-text-stroke: 2px black;
|
||||
text-stroke: 2px black;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
max-width: 80em;
|
||||
}
|
||||
|
||||
.box {
|
||||
padding: 1em;
|
||||
border-color: #ff7700;
|
||||
outline: 1px solid #ff7700;
|
||||
background-color: #000;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
hr.is-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.image.is-32x32, .is-32x32 img, img.is-32x32 {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.image.is-48x48, .is-48x48 img, img.is-48x48 {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.image.is-64x64, .is-64x64 img, img.is-64x64 {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.image.is-96x96, .is-96x96 img, img.is-96x96 {
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
}
|
||||
|
||||
.is-max-128 {
|
||||
max-height: 128px;
|
||||
max-width: 128px;
|
||||
}
|
||||
|
||||
.is-max-256 {
|
||||
max-height: 256px;
|
||||
max-width: 256px;
|
||||
}
|
||||
|
||||
|
||||
.media {
|
||||
background-color: black;
|
||||
border-radius: 5px;
|
||||
/*-webkit-box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1);
|
||||
box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1);*/
|
||||
color: #4a4a00;
|
||||
padding: 1.25rem;
|
||||
margin-bottom: 0.75rem;
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
.is-max-128 {
|
||||
max-height: 128px;
|
||||
max-width: 128px;
|
||||
}
|
||||
|
||||
.is-max-256 {
|
||||
max-height: 256px;
|
||||
max-width: 256px;
|
||||
}
|
||||
|
||||
figure.media-left p.image a img
|
||||
{
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.active-context {
|
||||
background-color: #000000;
|
||||
border-color: #ffcc00;
|
||||
outline: 1px solid #ffcc00;
|
||||
}
|
||||
|
||||
.account-avatar
|
||||
{
|
||||
display: inline-block;
|
||||
}
|
||||
.reblog-icon
|
||||
{
|
||||
margin-top: 32px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
img.fav-avatar {
|
||||
display: inline;
|
||||
|
||||
}
|
||||
|
||||
.level {
|
||||
display: block;
|
||||
margin-bottom: 1ex;
|
||||
margin-top: 1ex;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.media {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1024px) {
|
||||
.navbar,
|
||||
.navbar-menu,
|
||||
.navbar-start,
|
||||
.navbar-end {
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
}
|
||||
.navbar-start {
|
||||
justify-content: flex-start;
|
||||
margin-right: auto;
|
||||
}
|
||||
.navbar-end {
|
||||
justify-content: flex-end;
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
188
brutaldon/static/css/vt240don-green.css
Normal file
188
brutaldon/static/css/vt240don-green.css
Normal file
@ -0,0 +1,188 @@
|
||||
html, body, a, div, div.notification, body, body div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header, menu, nav, section, time, mark, audio, video, details, summary, h1.title, h2.subtitle {
|
||||
font-family: "monospace";
|
||||
color: #00ff77;
|
||||
background-color: #000;
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
|
||||
tr, td, ul, ol {
|
||||
border-color: #00ff77;
|
||||
outline: 1px solid #00ff77;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
a, a.button, a.button.is-primary, input.button.is-primary, input, .input, .textarea, .footer, .label, select, textarea {
|
||||
color: #00ff88;
|
||||
border-color: #00ff88;
|
||||
background-color: #000000;
|
||||
font-weight: bolder;
|
||||
text-decoration-line: none;
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
|
||||
a:hover, a.button:hover, a.button.is-primary:hover, input.button.is-primary:hover {
|
||||
color: #000000;
|
||||
background-color: #00ff88;
|
||||
}
|
||||
|
||||
.control input[type=text], .control textarea
|
||||
{
|
||||
width: 100%;
|
||||
max-width: 80em;
|
||||
border: 1px solid #00ff77;
|
||||
background-color: #000000;
|
||||
margin-bottom: 1ex;
|
||||
}
|
||||
|
||||
.control input, .control select
|
||||
{
|
||||
border: 1px solid #00ff77;
|
||||
background-color: #000000;
|
||||
margin-bottom: 1ex;
|
||||
}
|
||||
|
||||
img {
|
||||
filter: grayscale(100%);
|
||||
-webkit-filter: grayscale(100%);
|
||||
}
|
||||
|
||||
|
||||
div.card-header-title, div.card-header-icon {
|
||||
color: #00ff77;
|
||||
-webkit-text-stroke: 2px black;
|
||||
-moz-text-stroke: 2px black;
|
||||
text-stroke: 2px black;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
max-width: 80em;
|
||||
color: #00ff88;
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
.box {
|
||||
padding: 1em;
|
||||
border-color: #00ff77;
|
||||
outline: 1px solid #00ff77;
|
||||
background-color: #000;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
hr.is-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.image.is-32x32, .is-32x32 img, img.is-32x32 {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.image.is-48x48, .is-48x48 img, img.is-48x48 {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.image.is-64x64, .is-64x64 img, img.is-64x64 {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.image.is-96x96, .is-96x96 img, img.is-96x96 {
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
}
|
||||
|
||||
.is-max-128 {
|
||||
max-height: 128px;
|
||||
max-width: 128px;
|
||||
}
|
||||
|
||||
.is-max-256 {
|
||||
max-height: 256px;
|
||||
max-width: 256px;
|
||||
}
|
||||
|
||||
|
||||
.media {
|
||||
background-color: black;
|
||||
border-radius: 5px;
|
||||
/*-webkit-box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1);
|
||||
box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1);*/
|
||||
color: #4a4a00;
|
||||
padding: 1.25rem;
|
||||
margin-bottom: 0.75rem;
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
.is-max-128 {
|
||||
max-height: 128px;
|
||||
max-width: 128px;
|
||||
}
|
||||
|
||||
.is-max-256 {
|
||||
max-height: 256px;
|
||||
max-width: 256px;
|
||||
}
|
||||
|
||||
figure.media-left p.image a img
|
||||
{
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.active-context {
|
||||
background-color: #000000;
|
||||
border-color: #00ff88;
|
||||
outline: 1px solid #00ff88;
|
||||
}
|
||||
|
||||
.account-avatar
|
||||
{
|
||||
display: inline-block;
|
||||
}
|
||||
.reblog-icon
|
||||
{
|
||||
margin-top: 32px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
img.fav-avatar {
|
||||
display: inline;
|
||||
|
||||
}
|
||||
|
||||
.level {
|
||||
display: block;
|
||||
margin-bottom: 1ex;
|
||||
margin-top: 1ex;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.media {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1024px) {
|
||||
.navbar,
|
||||
.navbar-menu,
|
||||
.navbar-start,
|
||||
.navbar-end {
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
}
|
||||
.navbar-start {
|
||||
justify-content: flex-start;
|
||||
margin-right: auto;
|
||||
}
|
||||
.navbar-end {
|
||||
justify-content: flex-end;
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
@ -13,16 +13,22 @@
|
||||
brutaldon
|
||||
{% endif %}
|
||||
{% endblock %}</title>
|
||||
{% if not fullbrutalism %}
|
||||
<link rel="stylesheet"
|
||||
href="{% static 'css/bulma.min.css' %}">
|
||||
<link rel="stylesheet"
|
||||
href="{% static 'css/fork-awesome.min.css' %}">
|
||||
<link rel="stylesheet" href="{% static "css/brutaldon.css" %}">
|
||||
{% block page_scripts %}
|
||||
{% endblock %}
|
||||
{% else %}
|
||||
<link rel="stylesheet" href="{% static "css/fullbrutalism.css" %}" >
|
||||
{% if not preferences %}
|
||||
<link rel="stylesheet"
|
||||
href="{% static 'css/bulma.min.css' %}">
|
||||
<link rel="stylesheet"
|
||||
href="{% static 'css/fork-awesome.min.css' %}">
|
||||
<link rel="stylesheet" href="{% static "css/brutaldon.css" %}">
|
||||
{% else %}
|
||||
<link rel="stylesheet"
|
||||
href="{% static preferences.theme.main_css %}">
|
||||
<link rel="stylesheet" href="{% static preferences.theme.tweaks_css %}">
|
||||
{% if not preferences.theme.is_brutalist %}
|
||||
<link rel="stylesheet"
|
||||
href="{% static 'css/fork-awesome.min.css' %}">
|
||||
{% block page_scripts %}
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if own_acct %}
|
||||
<link rel="icon" href="{{ own_acct.avatar_static }}">
|
||||
@ -32,7 +38,7 @@
|
||||
</head>
|
||||
<body class="has-navbar-fixed-top">
|
||||
{% block navbar %}
|
||||
<nav class="navbar is-fixed-top is-light" role="navigation"
|
||||
<nav class="navbar is-fixed-top" role="navigation"
|
||||
aria-label="main navigation">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="{% url "home" %}">
|
||||
@ -115,7 +121,7 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="level-right">
|
||||
{% if fullbrutalism %}
|
||||
{% if preferences.theme.is_brutalist %}
|
||||
<img class="level-item" src="{% static '/images/lynx.gif' %}"
|
||||
alt="Lynx Now!">
|
||||
<img class="level-item" src="{% static '/images/now9.gif' %}"
|
||||
@ -128,7 +134,7 @@
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{% if not fullbrutalism %}
|
||||
{% if not preferences.theme.is_brutalist %}
|
||||
|
||||
<script type="application/javascript">
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
@ -128,7 +128,7 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% if not fullbrutalism %}
|
||||
{% if not preferences.theme.is_brutalist %}
|
||||
<script type="application/javascript">
|
||||
var file1 = document.getElementById("id_media_file_1");
|
||||
file1.onchange = function(){
|
||||
|
@ -5,9 +5,9 @@
|
||||
{% load static %}
|
||||
|
||||
{% if active %}
|
||||
<article class="media active-context">
|
||||
<article class="media box active-context">
|
||||
{% else %}
|
||||
<article class="media">
|
||||
<article class="media box">
|
||||
{% endif %}
|
||||
|
||||
<figure class="media-left">
|
||||
|
@ -10,7 +10,7 @@ Brutaldon ({{ own_acct.username }}) - {{ user.acct }} timelime
|
||||
{% block content %}
|
||||
|
||||
<div class="card">
|
||||
{% if not fullbrutalism %}
|
||||
{% if not preferences.theme.is_brutalist %}
|
||||
<div class="card-header" style="background-image: url({{ user.header }});">
|
||||
{% else %}
|
||||
<div class="card-header">
|
||||
|
@ -17,9 +17,9 @@
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label">{{ form.username.label }}</label>
|
||||
<label class="label">{{ form.email.label }}</label>
|
||||
<div class="control has-icons-left">
|
||||
{% render_field form.username class+="input" %}
|
||||
{% render_field form.email class+="input" %}
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fa fa-user"></i>
|
||||
</span>
|
||||
|
@ -2,40 +2,48 @@
|
||||
{% load widget_tweaks %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="title">Settings</h1>
|
||||
<form method="post" action="{% url "settings" %}" >
|
||||
{% csrf_token %}
|
||||
<div class="field">
|
||||
<label class="label checkbox">
|
||||
{% render_field form.fullbrutalism %}
|
||||
{{ form.fullbrutalism.label }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label checkbox">
|
||||
{% render_field form.filter_replies %}
|
||||
{{ form.filter_replies.label }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label checkbox"">
|
||||
{% render_field form.filter_boosts %}
|
||||
{{ form.filter_boosts.label }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label" for="timezone">{{ form.timezone.label }}</label>
|
||||
<div class="control has-icons-left">
|
||||
<div class="select">
|
||||
{% render_field form.timezone class+="select" %}
|
||||
<span class="icon is-small is-left">
|
||||
<span class="fa fa-clock-o"></span>
|
||||
</div>
|
||||
<div class="container">
|
||||
<h1 class="title">Settings</h1>
|
||||
<form method="post" action="{% url "settings" %}" >
|
||||
{% csrf_token %}
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label" for="theme">{{ form.theme.label }}</label>
|
||||
<div class="control has-icons-left">
|
||||
<div class="select">
|
||||
{% render_field form.theme class+="select" %}
|
||||
<span class="icon is-small is-left">
|
||||
<span class="fa fa-paint-brush"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<input type="submit" name="submit"
|
||||
value="Save" class="button is-primary" >
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="label checkbox">
|
||||
{% render_field form.filter_replies %}
|
||||
{{ form.filter_replies.label }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label checkbox"">
|
||||
{% render_field form.filter_boosts %}
|
||||
{{ form.filter_boosts.label }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label" for="timezone">{{ form.timezone.label }}</label>
|
||||
<div class="control has-icons-left">
|
||||
<div class="select">
|
||||
{% render_field form.timezone class+="select" %}
|
||||
<span class="icon is-small is-left">
|
||||
<span class="fa fa-clock-o"></span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="field">
|
||||
<input type="submit" name="submit"
|
||||
value="Save" class="button is-primary" >
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -5,12 +5,11 @@ from django.urls import reverse
|
||||
from django.views.decorators.cache import never_cache, cache_page
|
||||
from django.urls import reverse
|
||||
from django.core.files.uploadhandler import TemporaryFileUploadHandler
|
||||
from brutaldon.forms import LoginForm, OAuthLoginForm, SettingsForm, PostForm
|
||||
from brutaldon.models import Client, Account
|
||||
from brutaldon.forms import LoginForm, OAuthLoginForm, PreferencesForm, PostForm
|
||||
from brutaldon.models import Client, Account, Preference, Theme
|
||||
from mastodon import Mastodon, AttribAccessDict, MastodonError
|
||||
from urllib import parse
|
||||
from pdb import set_trace
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
class NotLoggedInException(Exception):
|
||||
pass
|
||||
@ -22,52 +21,26 @@ class Singleton(type):
|
||||
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
|
||||
return cls._instances[cls]
|
||||
|
||||
class MastodonPool(dict, metaclass=Singleton):
|
||||
pass
|
||||
|
||||
def get_mastodon(request):
|
||||
pool = MastodonPool()
|
||||
if request.session.has_key('access_token'):
|
||||
try:
|
||||
client = Client.objects.get(api_base_id=request.session['instance'])
|
||||
except (Client.DoesNotExist, Client.MultipleObjectsReturned):
|
||||
raise NotLoggedInException()
|
||||
if request.session['access_token'] in pool.keys():
|
||||
mastodon = pool[request.session['access_token']]
|
||||
else:
|
||||
mastodon = Mastodon(
|
||||
client_id = client.client_id,
|
||||
client_secret = client.client_secret,
|
||||
api_base_url = client.api_base_id,
|
||||
access_token = request.session['access_token'],
|
||||
ratelimit_method='throw')
|
||||
pool[request.session['access_token']] = mastodon
|
||||
else:
|
||||
def get_usercontext(request):
|
||||
if is_logged_in(request):
|
||||
try:
|
||||
client = Client.objects.get(api_base_id=request.session['instance'])
|
||||
user = Account.objects.get(username=request.session['username'])
|
||||
except (Client.DoesNotExist, Client.MultipleObjectsReturned,
|
||||
Account.DoesNotExist, Account.MultipleObjectsReturned):
|
||||
raise NotLoggedInException()
|
||||
if user.access_token in pool.keys():
|
||||
mastodon = pool[user.access_token]
|
||||
else:
|
||||
mastodon = Mastodon(
|
||||
client_id = client.client_id,
|
||||
client_secret = client.client_secret,
|
||||
access_token = user.access_token,
|
||||
api_base_url = client.api_base_id,
|
||||
ratelimit_method="throw")
|
||||
pool[user.access_token] = mastodon
|
||||
return mastodon
|
||||
|
||||
def fullbrutalism_p(request):
|
||||
return request.session.get('fullbrutalism', False)
|
||||
mastodon = Mastodon(
|
||||
client_id = client.client_id,
|
||||
client_secret = client.client_secret,
|
||||
access_token = user.access_token,
|
||||
api_base_url = client.api_base_id,
|
||||
ratelimit_method="throw")
|
||||
return user, mastodon
|
||||
else:
|
||||
return None, None
|
||||
|
||||
def is_logged_in(request):
|
||||
return (request.session.has_key('instance') and
|
||||
(request.session.has_key('username') or
|
||||
request.session.has_key('access_token')))
|
||||
return request.session.has_key('user')
|
||||
|
||||
def br_login_required(function=None, home_url=None, redirect_field_name=None):
|
||||
"""Check that the user is logged in to a Mastodon instance.
|
||||
@ -107,7 +80,7 @@ def br_login_required(function=None, home_url=None, redirect_field_name=None):
|
||||
return _dec(function)
|
||||
|
||||
def timeline(request, timeline='home', timeline_name='Home', max_id=None, since_id=None):
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
data = mastodon.timeline(timeline, limit=100, max_id=max_id, since_id=since_id)
|
||||
form = PostForm(initial={'visibility': request.session['user'].source.privacy})
|
||||
try:
|
||||
@ -122,15 +95,15 @@ def timeline(request, timeline='home', timeline_name='Home', max_id=None, since_
|
||||
next = None
|
||||
|
||||
# This filtering has to be done *after* getting next/prev links
|
||||
if request.session.get('filter_replies', False):
|
||||
if account.preferences.filter_replies:
|
||||
data = [x for x in data if not x.in_reply_to_id]
|
||||
if request.session.get('filter_boosts', False):
|
||||
if account.preferences.filter_boosts:
|
||||
data = [x for x in data if not x.reblog]
|
||||
return render(request, 'main/%s_timeline.html' % timeline,
|
||||
{'toots': data, 'form': form, 'timeline': timeline,
|
||||
'timeline_name': timeline_name,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request),
|
||||
'preferences': account.preferences,
|
||||
'prev': prev, 'next': next})
|
||||
|
||||
@br_login_required
|
||||
@ -148,14 +121,14 @@ def fed(request, next=None, prev=None):
|
||||
@br_login_required
|
||||
def tag(request, tag):
|
||||
try:
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
except NotLoggedInException:
|
||||
return redirect(login)
|
||||
data = mastodon.timeline_hashtag(tag)
|
||||
return render(request, 'main/timeline.html',
|
||||
{'toots': data, 'timeline_name': '#'+tag,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request)})
|
||||
'preferences': account.preferences})
|
||||
|
||||
@never_cache
|
||||
def login(request):
|
||||
@ -219,7 +192,27 @@ def oauth_callback(request):
|
||||
scopes=['read', 'write', 'follow'])
|
||||
request.session['access_token'] = access_token
|
||||
user = mastodon.account_verify_credentials()
|
||||
try:
|
||||
account = Account.objects.get(username=user.username)
|
||||
account.access_token = access_token
|
||||
if not account.preferences:
|
||||
preferences = Preference(theme = Theme.objects.get(id=1))
|
||||
preferences.save()
|
||||
account.preferences = preferences
|
||||
else:
|
||||
request.session['timezone'] = account.preferences.timezone
|
||||
account.save()
|
||||
except (Account.DoesNotExist, Account.MultipleObjectsReturned):
|
||||
preferences = Preference(theme = Theme.objects.get(id=1))
|
||||
preferences.save()
|
||||
account = Account(username=user.acct,
|
||||
access_token = access_token,
|
||||
client = Client.objects.get(api_base_id=request.session['instance']),
|
||||
preferences = preferences)
|
||||
request.session['user'] = user
|
||||
request.session['username'] = user.username
|
||||
account.username = user.username
|
||||
account.save()
|
||||
return redirect(home)
|
||||
|
||||
|
||||
@ -240,7 +233,7 @@ def old_login(request):
|
||||
api_base_url = api_base_url.lower()
|
||||
|
||||
request.session['instance'] = api_base_url
|
||||
username = form.cleaned_data['username']
|
||||
email = form.cleaned_data['email']
|
||||
password = form.cleaned_data['password']
|
||||
|
||||
try:
|
||||
@ -261,26 +254,30 @@ def old_login(request):
|
||||
api_base_url = api_base_url)
|
||||
|
||||
try:
|
||||
account = Account.objects.get(username=username, client_id=client.id)
|
||||
account = Account.objects.get(email=email, client_id=client.id)
|
||||
except (Account.DoesNotExist, Account.MultipleObjectsReturned):
|
||||
preferences = Preference(theme = Theme.objects.get(id=1))
|
||||
preferences.save()
|
||||
account = Account(
|
||||
username = username,
|
||||
email = email,
|
||||
access_token = "",
|
||||
client = client)
|
||||
client = client,
|
||||
preferences = preferences)
|
||||
try:
|
||||
access_token = mastodon.log_in(username,
|
||||
password,
|
||||
scopes=['read', 'write', 'follow'])
|
||||
account.access_token = access_token
|
||||
account.save()
|
||||
request.session['username'] = username
|
||||
user = mastodon.account_verify_credentials()
|
||||
request.session['user'] = user
|
||||
|
||||
request.session['username'] = user.username
|
||||
account.username = user.username
|
||||
request.session['timezone'] = account.preferences.timezone;
|
||||
account.save()
|
||||
return redirect(home)
|
||||
|
||||
except Exception as ex:
|
||||
form.add_error('', ex)
|
||||
|
||||
return render(request, 'setup/login.html', {'form': form})
|
||||
else:
|
||||
return render(request, 'setup/login.html', {'form': form})
|
||||
@ -296,7 +293,7 @@ def error(request):
|
||||
@br_login_required
|
||||
def note(request, next=None, prev=None):
|
||||
try:
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
except NotLoggedInException:
|
||||
return redirect(about)
|
||||
notes = mastodon.notifications(limit=100, max_id=next, since_id=prev)
|
||||
@ -314,23 +311,23 @@ def note(request, next=None, prev=None):
|
||||
{'notes': notes,'timeline': 'Notifications',
|
||||
'timeline_name': 'Notifications',
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request),
|
||||
'preferences': account.preferences,
|
||||
'prev': prev, 'next': next})
|
||||
|
||||
@br_login_required
|
||||
def thread(request, id):
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
context = mastodon.status_context(id)
|
||||
toot = mastodon.status(id)
|
||||
return render(request, 'main/thread.html',
|
||||
{'context': context, 'toot': toot,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request)})
|
||||
'preferences': account.preferences})
|
||||
|
||||
@br_login_required
|
||||
def user(request, username, prev=None, next=None):
|
||||
try:
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
except NotLoggedInException:
|
||||
return redirect(about)
|
||||
try:
|
||||
@ -354,41 +351,40 @@ def user(request, username, prev=None, next=None):
|
||||
{'toots': data, 'user': user_dict,
|
||||
'relationship': relationship,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request),
|
||||
'preferences': account.preferences,
|
||||
'prev': prev, 'next': next})
|
||||
|
||||
|
||||
@never_cache
|
||||
@br_login_required
|
||||
def settings(request):
|
||||
account = Account.objects.get(username=request.session['username'])
|
||||
if request.method == 'POST':
|
||||
form = SettingsForm(request.POST)
|
||||
form = PreferencesForm(request.POST)
|
||||
if form.is_valid():
|
||||
request.session['fullbrutalism'] = form.cleaned_data['fullbrutalism']
|
||||
request.session['filter_replies'] = form.cleaned_data['filter_replies']
|
||||
request.session['filter_boosts'] = form.cleaned_data['filter_boosts']
|
||||
request.session['timezone'] = form.cleaned_data['timezone']
|
||||
account.preferences.theme =form.cleaned_data['theme']
|
||||
account.preferences.filter_replies = form.cleaned_data['filter_replies']
|
||||
account.preferences.filter_boosts = form.cleaned_data['filter_boosts']
|
||||
account.preferences.timezone = form.cleaned_data['timezone']
|
||||
request.session['timezone'] = account.preferences.timezone
|
||||
account.preferences.save()
|
||||
account.save()
|
||||
return redirect(home)
|
||||
else:
|
||||
return render(request, 'setup/settings.html',
|
||||
{'form' : form,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request)})
|
||||
{'form' : form, 'account': account})
|
||||
else:
|
||||
form = SettingsForm(initial={
|
||||
"fullbrutalism": fullbrutalism_p(request),
|
||||
"filter_replies": request.session.get('filter_replies', False),
|
||||
"filter_boosts": request.session.get('filter_boosts', False),
|
||||
"timezone": request.session.get('timezone', 'UTC')
|
||||
})
|
||||
request.session['timezone'] = account.preferences.timezone
|
||||
form = PreferencesForm(instance=account.preferences)
|
||||
return render(request, 'setup/settings.html',
|
||||
{ 'form': form,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request)})
|
||||
'account': account,
|
||||
'preferences': account.preferences})
|
||||
|
||||
@never_cache
|
||||
@br_login_required
|
||||
def toot(request, mention=None):
|
||||
account, mastodon = get_usercontext(request)
|
||||
if request.method == 'GET':
|
||||
if mention:
|
||||
if not mention.startswith('@'):
|
||||
@ -400,12 +396,10 @@ def toot(request, mention=None):
|
||||
return render(request, 'main/post.html',
|
||||
{'form': form,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request)})
|
||||
'preferences': account.preferences})
|
||||
elif request.method == 'POST':
|
||||
form = PostForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
mastodon = get_mastodon(request)
|
||||
|
||||
# create media objects
|
||||
media_objects = []
|
||||
for index in range(1,5):
|
||||
@ -427,14 +421,14 @@ def toot(request, mention=None):
|
||||
return render(request, 'main/post.html',
|
||||
{'form': form,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request)})
|
||||
'preferences': account.preferences})
|
||||
else:
|
||||
return redirect(toot)
|
||||
|
||||
@br_login_required
|
||||
def redraft(request, id):
|
||||
if request.method == 'GET':
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
toot = mastodon.status(id)
|
||||
toot_content = BeautifulSoup(toot.content).get_text("\n")
|
||||
form = PostForm({'status': toot_content,
|
||||
@ -448,10 +442,10 @@ def redraft(request, id):
|
||||
return render(request, 'main/redraft.html',
|
||||
{'toot': toot, 'form': form, 'redraft':True,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request)})
|
||||
'preferences': account.preferences})
|
||||
elif request.method == 'POST':
|
||||
form = PostForm(request.POST, request.FILES)
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
toot = mastodon.status(id)
|
||||
if form.is_valid():
|
||||
media_objects = []
|
||||
@ -476,7 +470,7 @@ def redraft(request, id):
|
||||
return render(request, 'main/redraft.html',
|
||||
{'toot': toot, 'form': form, 'redraft': True,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request)})
|
||||
'preferences': account.preferences})
|
||||
else:
|
||||
return redirect(redraft, id)
|
||||
|
||||
@ -495,7 +489,7 @@ def safe_get_attachment(toot, index):
|
||||
@br_login_required
|
||||
def reply(request, id):
|
||||
if request.method == 'GET':
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
toot = mastodon.status(id)
|
||||
context = mastodon.status_context(id)
|
||||
if toot.account.acct != request.session['user'].acct:
|
||||
@ -512,10 +506,10 @@ def reply(request, id):
|
||||
return render(request, 'main/reply.html',
|
||||
{'context': context, 'toot': toot, 'form': form, 'reply':True,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request)})
|
||||
'preferences': account.preferences})
|
||||
elif request.method == 'POST':
|
||||
form = PostForm(request.POST, request.FILES)
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
if form.is_valid():
|
||||
# create media objects
|
||||
media_objects = []
|
||||
@ -539,14 +533,14 @@ def reply(request, id):
|
||||
return render(request, 'main/reply.html',
|
||||
{'context': context, 'toot': toot, 'form': form, 'reply': True,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request)})
|
||||
'preferences': account.preferences})
|
||||
else:
|
||||
return redirect(reply, id)
|
||||
|
||||
@never_cache
|
||||
@br_login_required
|
||||
def fav(request, id):
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
toot = mastodon.status(id)
|
||||
if request.method == 'POST':
|
||||
if not request.POST.get('cancel', None):
|
||||
@ -560,12 +554,12 @@ def fav(request, id):
|
||||
{"toot": toot,
|
||||
'own_acct': request.session['user'],
|
||||
"confirm_page": True,
|
||||
'fullbrutalism': fullbrutalism_p(request)})
|
||||
'preferences': account.preferences})
|
||||
|
||||
@never_cache
|
||||
@br_login_required
|
||||
def boost(request, id):
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
toot = mastodon.status(id)
|
||||
if request.method == 'POST':
|
||||
if not request.POST.get('cancel', None):
|
||||
@ -579,12 +573,12 @@ def boost(request, id):
|
||||
{"toot": toot,
|
||||
'own_acct': request.session['user'],
|
||||
'confirm_page': True,
|
||||
"fullbrutalism": fullbrutalism_p(request)})
|
||||
"preferences": account.preferences})
|
||||
|
||||
@never_cache
|
||||
@br_login_required
|
||||
def delete(request, id):
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
toot = mastodon.status(id)
|
||||
if request.method == 'POST':
|
||||
if toot.account.acct != request.session['user'].acct:
|
||||
@ -597,12 +591,12 @@ def delete(request, id):
|
||||
{"toot": toot,
|
||||
'own_acct': request.session['user'],
|
||||
'confirm_page': True,
|
||||
"fullbrutalism": fullbrutalism_p(request)})
|
||||
"preferences": account.preferences})
|
||||
|
||||
@never_cache
|
||||
@br_login_required
|
||||
def follow(request, id):
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
try:
|
||||
user_dict = mastodon.account(id)
|
||||
relationship = mastodon.account_relationships(user_dict.id)[0]
|
||||
@ -620,12 +614,12 @@ def follow(request, id):
|
||||
{"user": user_dict, "relationship": relationship,
|
||||
"confirm_page": True,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request)})
|
||||
'preferences': account.preferences})
|
||||
|
||||
@never_cache
|
||||
@br_login_required
|
||||
def block(request, id):
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
try:
|
||||
user_dict = mastodon.account(id)
|
||||
relationship = mastodon.account_relationships(user_dict.id)[0]
|
||||
@ -643,12 +637,12 @@ def block(request, id):
|
||||
{"user": user_dict, "relationship": relationship,
|
||||
"confirm_page": True,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request)})
|
||||
'preferences': account.preferences})
|
||||
|
||||
@never_cache
|
||||
@br_login_required
|
||||
def mute(request, id):
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
try:
|
||||
user_dict = mastodon.account(id)
|
||||
relationship = mastodon.account_relationships(user_dict.id)[0]
|
||||
@ -666,12 +660,13 @@ def mute(request, id):
|
||||
{"user": user_dict, "relationship": relationship,
|
||||
"confirm_page": True,
|
||||
'own_acct': request.session['user'],
|
||||
'fullbrutalism': fullbrutalism_p(request)})
|
||||
'preferences': account.preferences})
|
||||
|
||||
@br_login_required
|
||||
def search(request):
|
||||
account, mastodon = get_usercontext(request)
|
||||
return render(request, 'main/search.html',
|
||||
{"fullbrutalism": fullbrutalism_p(request),
|
||||
{"preferences": account.preferences,
|
||||
'own_acct': request.session['user'],
|
||||
})
|
||||
|
||||
@ -683,31 +678,37 @@ def search_results(request):
|
||||
query = request.POST.get('q', '')
|
||||
else:
|
||||
query = ''
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
results = mastodon.search(query)
|
||||
return render(request, 'main/search_results.html',
|
||||
{"results": results,
|
||||
'own_acct': request.session['user'],
|
||||
"fullbrutalism": fullbrutalism_p(request)})
|
||||
"preferences": account.preferences})
|
||||
|
||||
def about(request):
|
||||
version = django_settings.BRUTALDON_VERSION
|
||||
account, mastodon = get_usercontext(request)
|
||||
if account:
|
||||
preferences = account.preferences
|
||||
else:
|
||||
preferences = None
|
||||
return render(request, 'about.html',
|
||||
{"fullbrutalism": fullbrutalism_p(request),
|
||||
{"preferences": preferences,
|
||||
"version": version,
|
||||
'own_acct': request.session.get('user', None),
|
||||
})
|
||||
def privacy(request):
|
||||
account, mastodon = get_usercontext(request)
|
||||
return render(request, 'privacy.html',
|
||||
{"fullbrutalism": fullbrutalism_p(request),
|
||||
{"preferences": preferences,
|
||||
'own_acct' : request.session.get('user', None)})
|
||||
|
||||
@cache_page(60 * 30)
|
||||
@br_login_required
|
||||
def emoji_reference(request):
|
||||
mastodon = get_mastodon(request)
|
||||
account, mastodon = get_usercontext(request)
|
||||
emojos = mastodon.custom_emojis()
|
||||
return render(request, 'main/emoji.html',
|
||||
{"fullbrutalism": fullbrutalism_p(request),
|
||||
{"preferences": account.preferences,
|
||||
"emojos": sorted(emojos, key=lambda x: x['shortcode']),
|
||||
'own_acct' : request.session['user']})
|
||||
|
Loading…
Reference in New Issue
Block a user