Compare commits

...

273 commits

Author SHA1 Message Date
f547812d5a Added RPC endpoint for fetching user info. 2024-09-05 20:08:31 +00:00
8a06836985 Added auth RPC routes. 2024-08-25 23:03:46 +00:00
34528ae413 Fixed return type. 2024-08-18 20:54:39 +00:00
0bf7ca0d52 Replaced internal Flashii ID routes with RPC library. 2024-08-16 19:29:57 +00:00
cc9fccdf18 Updated Index and switched to Carbon for date handling. 2024-08-04 21:37:12 +00:00
ca77b501e7 Removed stray Jeff. 2024-07-27 20:11:06 +00:00
2439f87df9 Added very preliminary support for Bearer tokens to chat authentication. 2024-07-21 01:50:42 +00:00
400253e04b Added interop endpoints for Hanyuu. 2024-07-20 19:35:50 +00:00
01c60e3027 Updated libraries. 2024-07-18 03:42:16 +00:00
37d8413118 Updated build script. 2024-06-11 00:48:44 +00:00
8cfa07bc8c SharpConfig -> FileConfig 2024-06-03 23:04:59 +00:00
a65579bf9d Updated libraries. 2024-06-03 23:04:21 +00:00
44a4bb6e6f Prevent access to private messages when impersonating a user. 2024-06-02 19:57:58 +00:00
ec00cfa176 Base64 encode PM titles and bodies in the database.
To prevent personal discomfort with having to do database messages and seeing people's personal conversations.
I haven't run into it yet, but I'd rather avoid it altogether.
2024-06-02 19:54:33 +00:00
1d295df8da Added broom closet PM stats. 2024-06-02 19:43:57 +00:00
6a88ed8b11 Updated libraries. 2024-05-30 22:02:09 +00:00
36bcf1ab1d Built Playpen icon updating into Misuzu.
Was previously handled by a stinky script.
2024-05-30 22:00:41 +00:00
5d3e1d4960 Fixed wrong HTTP verb. 2024-03-30 15:22:11 +00:00
9bb943bacf Fixed various oversights. 2024-03-30 03:19:08 +00:00
107d16cf46 Updated Misuzu to new HTTP router. 2024-03-30 03:14:03 +00:00
0afc5186a7 Fixed error when trying to access a topic with no posts associated. 2024-02-24 22:03:32 +00:00
0300bae994 hurr 2024-02-21 00:31:25 +00:00
cb0c64f8ed Stinky fix for impersonation in chat auth. 2024-02-20 23:56:43 +00:00
89ef9d9ad1 Fixed bans no longer working. 2024-02-15 22:55:24 +00:00
c02d922dc6 Fixed Forum Activity section always showing up. 2024-02-13 21:22:56 +00:00
80cd6222c4 Fixed profile fields not showing up anymore. 2024-02-11 02:22:22 +00:00
344a3c9160 Missed one! 2024-02-09 16:07:43 +00:00
df5dbdf3ad Fixed forum/topic breadcrumbs. 2024-02-08 15:20:44 +00:00
c0caceed7b Fixed use of wrong BanInfo constructor. 2024-02-08 15:18:57 +00:00
be54ce2c22 Fixed oversights on landing page. 2024-02-08 00:06:23 +00:00
070dc5e782 Added lazy database object creation. 2024-02-07 00:04:45 +00:00
b89621cb1a Added PMs to data export. 2024-02-05 22:56:51 +00:00
760cca0e5d whoops 2024-02-02 21:53:36 +00:00
fe77f1616c Updated to new EEPROM script. 2024-02-02 21:42:40 +00:00
eb81ed7a82 Added notice when recipient is banned. 2024-02-02 02:16:37 +00:00
8ef11afe02 Check if recipient is actually able to receive messages. 2024-02-02 02:07:29 +00:00
cca016ba10 Prevent banned users from sending messages. 2024-02-02 01:59:21 +00:00
b80151583e Added private messages. 2024-01-30 23:47:02 +00:00
d8cc208a85 Use accent-color and color-scheme CSS directives. 2024-01-25 18:17:54 +00:00
4b2f9a2fec Fixed Ctrl+Enter submission not working anymore either. 2024-01-25 00:18:56 +00:00
ddb255bf32 Fixed forum post form throwing up the navigation confirmation when it isn't supposed to. 2024-01-25 00:12:53 +00:00
5a70e3f3f1 Include SameSite attribute on cookies. 2024-01-24 22:14:48 +00:00
bd3e055323 Rewrote Javascript code. 2024-01-24 21:53:26 +00:00
dba5754ccc Fixed error when trying to add a new change. 2024-01-24 18:28:13 +00:00
ec6ba3f781 Imported new asset build script. 2024-01-24 18:24:40 +00:00
70ec285f99 Added links to Amimami repositories. 2024-01-18 20:31:08 +00:00
77eadd5bde Adjusted CORS handling for emoticon endpoint. 2024-01-17 19:57:46 +00:00
f0fc735975 Updated browserlists. 2024-01-08 13:43:34 +00:00
adb80bad9e Added server side image map support. 2024-01-08 13:42:22 +00:00
f30cf41f86 Ported boolean attribute support. 2024-01-08 13:36:47 +00:00
b4f5dd0660 Removed broken CONSTRAINT from perms table creation. 2023-12-16 18:51:17 +00:00
133e2f420c Fixed markdown styling issues. 2023-12-15 12:56:08 +00:00
bf65c95490 Updated highlight.js and created new code theme. 2023-12-15 12:47:01 +00:00
7ef5994da4 Updated Sentry library to 4.0 in Misuzu. 2023-12-15 01:03:57 +00:00
2b34bde413 Fixed error when trying to create a new role. 2023-12-02 02:57:46 +00:00
432615508d Fixed undefined variable. 2023-11-26 22:23:47 +00:00
a4cc14e4c1 Libraries have been updated once more. 2023-11-20 19:10:47 +00:00
65e695e9d9 git.flash.moe -> patchii.net 2023-11-20 19:04:59 +00:00
2e6a84b46d Updated source.md. 2023-11-09 20:58:56 +00:00
8f56174637 Supply super user status in auth data. 2023-11-07 14:38:53 +00:00
19fbe59ddd Return to purple. 2023-11-01 09:36:49 +00:00
f7a571e551 moguu? 2023-10-21 23:54:41 +00:00
5f57e3fdf4 Use SharpConfig format for the pre-database config. 2023-10-21 23:45:40 +00:00
c2836719c7 Updated to use Syokuhou config library. 2023-10-20 22:29:28 +00:00
14c9a1d9f6 Fixed oversight on members list. 2023-10-18 10:16:32 +00:00
4f1e35b566 Fixed overly eager url encoding on the search page. 2023-10-18 10:11:21 +00:00
9aa2a1431e Enable Spookii 2023-10-01 18:44:59 +00:00
4322f2561c Fixed chat routes being broken. 2023-09-11 20:36:20 +00:00
67d9620037 Fixed legacy paths being too / tolerant. 2023-09-11 20:15:48 +00:00
904d220582 Fixed router related explosions. 2023-09-11 20:10:37 +00:00
d9b152fb78 Fixed oversight on memberlist. 2023-09-11 19:19:19 +00:00
a945cc518a Fixed syntax error in post.php. 2023-09-11 19:18:10 +00:00
edc64b45ff Fixed error when trying to view a non-existent topic when logged out. 2023-09-10 21:04:10 +00:00
17e0d1f591 Added Sentry error logging on the server side. 2023-09-10 20:46:58 +00:00
5554c5c28d Removed unused pagination helper function. 2023-09-10 20:12:27 +00:00
55e23c7b5d Fixed CSRF tokens not being added to URLs that need them. 2023-09-10 20:02:11 +00:00
e376671136 Attempt at fixing forum issues. 2023-09-10 19:13:36 +00:00
3e49f6e503 Added URL registry attributes. 2023-09-10 00:04:53 +00:00
7db43a2acd Revert "チルノの日"
This reverts commit 099bd899ed.
2023-09-09 11:54:33 +00:00
099bd899ed チルノの日 2023-09-08 23:07:37 +00:00
1248c0d2f6 Moved various .php file redirects into the LegacyRouter. 2023-09-08 20:47:54 +00:00
c3bed1c0e3 Rewrote URL registry. 2023-09-08 20:40:48 +00:00
163da8b213 Added separate context class for forum stuff and split up handling of each object type. 2023-09-08 13:22:46 +00:00
c68279add9 Cleaned up some things I missed. 2023-09-08 01:05:17 +00:00
737c99280e Make PHPStan happy. 2023-09-08 00:54:19 +00:00
8b0f960c86 Split auth stuff off into own context. 2023-09-08 00:43:00 +00:00
c5a284f360 Route registration with attributes! 2023-09-08 00:13:30 +00:00
506d32d210 Fixed incorrect type on latest forum post fetching result. 2023-09-07 20:53:19 +00:00
498ec0cf9a Merge SharpChat permission set into the Misuzu permission system directly. 2023-09-06 20:44:28 +00:00
15e96684c2 Moved authentication related macros out of MisuzuContext. 2023-09-06 20:06:07 +00:00
73e4597e16 Rewrote Satori recent forum post fetch. 2023-09-06 19:35:50 +00:00
9b2c409a24 Moved user related stuff into its own context object. 2023-09-06 13:50:19 +00:00
7190a5f4df Syntactic sugar for mass route registration. 2023-09-06 11:59:44 +00:00
5c67d49225 Fixed edit display threshold. 2023-09-06 11:32:13 +00:00
69e4d05be6 Pluralise Views. 2023-09-06 11:19:54 +00:00
2d0f083e1a Fixed topic read status check. 2023-09-06 11:19:04 +00:00
1da6470928 Switch to Sasae. 2023-08-31 21:33:34 +00:00
9682fa595a Fixed static analysis detections. 2023-08-31 17:14:41 +00:00
c14195c4c3 Moved render_info and render_error into Template class. 2023-08-31 15:59:53 +00:00
45500ce698 Removed html_colour function, moved renamed DateCheck to Tools and moved the country names function into it and use new callable syntax. 2023-08-31 14:55:39 +00:00
0c9bac473b No longer rely on Referer header for the comments return URL. 2023-08-31 14:39:50 +00:00
061d4c8a8f Fixed leaderboard name not retaining the leading 0. 2023-08-31 00:54:17 +00:00
6fc10984e1 Append total posts count at the end of the leaderboard. 2023-08-31 00:52:14 +00:00
e222009dd0 Fixed oversight. 2023-08-31 00:40:07 +00:00
85b629bc08 Fixed missing use statement. 2023-08-31 00:38:20 +00:00
16ea495c7a Added permission for displaying load timings in the footer. 2023-08-31 00:37:09 +00:00
ad3fe74275 Removed old database backend. 2023-08-31 00:31:11 +00:00
29426fafc1 Count profile stats using Index database backend. 2023-08-31 00:24:59 +00:00
4d6fb64f3a Added shitty search hack to users class. 2023-08-31 00:19:20 +00:00
40558ceb39 Added targeted permission recalculation.
Reduces reliance on full recalculation and actually makes it viable to do from within the browser.
2023-08-30 23:56:33 +00:00
f03c8ebfa5 Moved validation methods into the new Users class. 2023-08-30 23:41:44 +00:00
07a2868159 Rewrote permissions system. 2023-08-30 22:37:21 +00:00
ca23822e40 Fixed errors on profiles. 2023-08-28 14:45:32 +00:00
34bd71600a Removed manage.php. 2023-08-28 13:45:36 +00:00
5bab957a7c Fixed user colours in comments sections. 2023-08-28 13:33:39 +00:00
57b9e82c10 Fixed topic type string usage. 2023-08-28 01:41:13 +00:00
460a0ca57d Fixed user colours not showing on forum posts. 2023-08-28 01:32:05 +00:00
39c6269cf3 Rewrote forum backend. 2023-08-28 01:17:34 +00:00
fb41c71ee9 Fixed emoticon ordering in chat. 2023-08-07 12:59:08 +00:00
2214dffc5b Fixed profile editing failing due to old argument. 2023-08-06 19:09:59 +00:00
bab8b29c5b Fixed error 500 when trying to log in to a non-existing user. 2023-08-06 18:22:39 +00:00
0a11c5525a Fixed oversight regarding RNG ordering of user list. 2023-08-05 13:55:34 +00:00
d4f6990e8a Made data source argument lists for News, Changelog, Comments and Emotes consistent with the rest. 2023-08-05 13:50:15 +00:00
87915b6a25 Fixed forum post deletion and editing. 2023-08-04 22:49:09 +00:00
cf71129153 Converted all Misuzu style route handlers to Index style ones. 2023-08-04 20:51:02 +00:00
6bfa3d7238 Fixed error 500 when viewing profiles as guest. 2023-08-04 17:44:37 +00:00
b7de5acfd8 Fixed search and updated collations of various fields to more appropriate ones. 2023-08-03 12:40:37 +00:00
9dd7156c79 Fixed issue caused by used of dangling variable on sessions page. 2023-08-03 01:43:43 +00:00
00d1d2922d Changed the way msz_auth is handled.
Going forward msz_auth is always assumed to be present, even while the user is not logged in.
If the cookie is not present a default, empty value will be used.
The msz_uid and msz_sid cookies are also still upconverted for some reason but are no longer removed even though there's no active sessions that can possibly have those anymore.
As with the previous change, shit may be broken so report any Anomalies you come across, through flashii-issues@flash.moe if necessary.
2023-08-03 01:35:08 +00:00
383e2ed0e0 Rewrote the user information class.
This one took multiple days and it pretty invasive into the core of Misuzu so issue might (will) arise, there's also some features that have gone temporarily missing in the mean time and some inefficiencies introduced that will be fixed again at a later time.
The old class isn't gone entirely because I still have to figure out what I'm gonna do about validation, but for the most part this knocks out one of the "layers of backwards compatibility", as I've been referring to it, and is moving us closer to a future where Flashii actually gets real updates.
If you run into anything that's broken and you're inhibited from reporting it through the forum, do it through chat or mail me at flashii-issues@flash.moe.
2023-08-02 22:12:47 +00:00
57081d858d Added server side stuff for Satori hooks. 2023-07-29 22:18:20 +00:00
e813f2a90e Some TOTP touch-ups. 2023-07-29 20:18:41 +00:00
0158333c90 Removed permissions stuff from the User object. 2023-07-29 18:15:30 +00:00
a89d8d26f4 Fixed error when news comments category doesn't exist somehow. 2023-07-29 18:01:41 +00:00
e3c0ae662e Removed HasRankInterface. 2023-07-29 17:31:43 +00:00
61daa21d3a Emit audit log upon impersonation. 2023-07-28 23:23:45 +00:00
934b016541 Added counters table for storing numbers of things statically. 2023-07-28 23:17:37 +00:00
8ef113f3a9 Allow non-super users to impersonate select users. 2023-07-28 21:20:19 +00:00
a22433f7dd Don't update last online time and ip address when impersonating. 2023-07-28 20:43:08 +00:00
c5ec94289d Added notice when there's no account logs to display. 2023-07-28 20:36:16 +00:00
8c52fc81e2 Hide roles section from settings if there's only one available. 2023-07-28 20:33:44 +00:00
d2f0eebfb2 Use random alphabetic string instead hex bytes for session tokens. 2023-07-28 20:13:11 +00:00
3148da4403 Rewrote Sessions backend. 2023-07-28 20:06:12 +00:00
5c8ffa09fc Cleaned up User and UserSession queries. 2023-07-28 15:07:30 +00:00
20b309563e Fixed phpstan detections. 2023-07-27 23:49:55 +00:00
461ffbf73b Rewrote user role handling. 2023-07-27 23:26:05 +00:00
26a0e11253 Fixed data export. 2023-07-27 13:14:32 +00:00
70623d3a7c Pluralise user role relations table name. 2023-07-27 13:09:22 +00:00
b4d4e8578c Rewrote TFA session code. 2023-07-27 12:44:50 +00:00
8480d5f043 Fixed the manage index statistics causing a 500 because the old warnings table is Gone. 2023-07-26 22:57:03 +00:00
a30df1b17c Fixed warning deletion. 2023-07-26 22:48:47 +00:00
351043e283 Split Sharp Chat kick and ban permissions based on the Misuzu warnings and bans permissions. 2023-07-26 22:46:35 +00:00
2231cd8124 Rewrote user warnings backend. 2023-07-26 22:43:50 +00:00
86432616c6 Expiration -> Expires 2023-07-26 18:24:49 +00:00
1d552e907b Added new banning system.
it actually works and isn't confusing this time around!
2023-07-26 18:19:48 +00:00
057551edb3 Pluralise. 2023-07-26 11:56:06 +00:00
710049794f Fixed typo that would cause things to fail. 2023-07-26 11:54:49 +00:00
ca1edb4270 Fixed gross misalignment. 2023-07-25 19:03:48 +00:00
f4f465d8d8 Redesigned news post preview information section. 2023-07-25 19:02:00 +00:00
81f4dfce19 Fixed error 500 when trying to view a non-existent profile. 2023-07-25 15:03:25 +00:00
bd683d8404 Allow moderators to view a stripped down version of the user page in the broom closet. 2023-07-25 14:52:51 +00:00
3299d73df2 Added new moderator notes system. 2023-07-25 14:40:31 +00:00
ee304af133 Removed the concept of silencing.
Nothing really implemented it properly or checked for it and the places that did check just handled it as a slightly softer ban.
It's pretty obvious that the existence of this feature was directly taken from osu! where the differentation between a ban and a silence probably makes more sense, though even there Silences are just non-permanent bans, so like why does this exist lol?
Well, it doesn't anymore! Hopefully chat will upgrade successfully because I let it get 18 commits behind :D
2023-07-23 21:47:15 +00:00
3d67b59238 Attempt 2 at fixing the profile fields issue (this one actually fixes the issue!) 2023-07-22 21:25:51 +00:00
dd21fce6e3 Rewrote password recovery token storage using new DB backend. 2023-07-22 21:20:03 +00:00
f6058823f1 Fixed error 500 on profiles when filling certain fields in specific conditions. 2023-07-22 20:54:52 +00:00
392881c0d8 Fixed type on getUserId in LoginAttemptInfo. 2023-07-22 17:27:42 +00:00
6e3023a772 Rewrite login attempts log to use new database backend. 2023-07-22 16:37:57 +00:00
d0e3f6ce65 Normalised custom exception usage in user classes.
Also updated the Index library to include the MediaType fix.
2023-07-22 15:02:45 +00:00
42d893fc18 Use the Index DbStatementCache implementation. 2023-07-22 14:00:51 +00:00
baefea88df Use the Index DbTools version for list prepare thing. 2023-07-22 13:54:42 +00:00
e369038609 Updated Index Serialiser usage. 2023-07-21 21:56:09 +00:00
9962bbc5df Added phpstan as a dev dependency. 2023-07-21 19:38:54 +00:00
761bc94b8e Removed local config plugin and fixed Index info pages. 2023-07-21 19:30:28 +00:00
ffbe25d0b5 Oops it's all white! 2023-07-21 19:17:57 +00:00
e4b647f2c6 Updated project licence to BSD3CC and import Index through Composer. 2023-07-21 18:58:37 +00:00
683462ef71 Just use Composer for DeviceDetector.
It was initially my goal to lessen use of Composer, but given I just switched to using NPM packages for asset compilation, it's a little bit silly to try and keep that going.
2023-07-21 16:12:08 +00:00
14c5635b4f Determine client info on insert rather than on retrieve for speed improvements.
i suppose device detect only ever expects to analyse a single string at once given its made for matomo so it on the slower side for multiple dingusses
2023-07-21 12:47:59 +00:00
ebac064c59 Fixed error 500 on logs and sessions pages because of dead library. 2023-07-21 11:33:27 +00:00
f32624c61d Improved profile fields code. 2023-07-20 19:36:43 +00:00
2e49940260 Upgrade to PHP 8.2. 2023-07-19 19:10:20 +00:00
24d61cc60e Removed lockdown feature for now. 2023-07-19 19:04:57 +00:00
029c1ff20e Restructured public folder and initialisation process. 2023-07-19 19:03:53 +00:00
c9993bf08b Display full join and seen dates on hover. 2023-07-19 18:18:27 +00:00
e678efedf4 Minor members list redesign. 2023-07-19 18:14:04 +00:00
239b0bae61 Removed overbearing global shadow. 2023-07-19 14:43:49 +00:00
30e77bd698 Removed leftover abstract class. 2023-07-19 14:34:02 +00:00
65549e3fa4 Fixed whatever the date formatter was smoking. 2023-07-18 23:19:19 +00:00
319f37a313 Removed server-side relative time. 2023-07-18 23:12:47 +00:00
bec58f589f Removed unnecessary checks from URL formatter. 2023-07-18 22:36:07 +00:00
473d5f22b5 Removed old formats of and unused SharpChat endpoints. 2023-07-18 22:33:13 +00:00
e6c826a7d7 Fixed various errors and oversights caught by phpstan. 2023-07-18 22:24:23 +00:00
2f7cddde19 Config class overhaul. 2023-07-18 21:48:44 +00:00
cecfaf4852 Removed timeago library. 2023-07-17 20:14:21 +00:00
e5d9128cd0 Fixed account data export memory usage. 2023-07-17 19:28:13 +00:00
1a11a8f8ba Rewrote audit log on new database backend. 2023-07-17 17:43:17 +00:00
96be282a93 Fixed Javascript not working because it's written very poorly. 2023-07-17 14:44:09 +00:00
074e078692 Use Node for asset building instead of building on the fly every time (feat. minification!) 2023-07-17 14:37:54 +00:00
f24f811acc Rewrote most of the comments backend.g 2023-07-15 23:58:17 +00:00
6274f7f8d3 Fixed some routing oversights. 2023-07-15 17:45:39 +00:00
472fc0decc Show Index and PDO query counts separately in the footer. 2023-07-15 17:15:40 +00:00
bff42c26ab Rewrote the news backend. 2023-07-15 17:02:46 +00:00
69c6b6f2ac Fixed various other oversights. 2023-07-15 02:14:39 +00:00
c56617e051 Fixed error on main page. 2023-07-15 02:08:13 +00:00
76c9cc50f4 Rewrote the Changelog code. 2023-07-15 02:05:49 +00:00
6d0d49171e Added more elegant method for statement caching. 2023-07-14 20:26:38 +00:00
3e2183b7b2 Fixed leap year birthdays without a year set. 2023-07-12 23:08:35 +00:00
3909cdf762 Rewrote backend for emoticons.
Manage actually works this time!!!
2023-07-12 21:52:55 +00:00
9b65ce005a Fixed possible NULL in CSRF check. 2023-07-12 19:14:40 +00:00
29165de457 Use the Index DSN to create the PDO based DB instance. 2023-07-11 22:45:23 +00:00
1186b0daeb Use Index for CSRF protection tokens. 2023-07-11 22:13:56 +00:00
ba8115fe10 CSRF and URL cleanup. 2023-07-11 20:51:24 +00:00
f025ee13d0 Rely on NGINX GeoIP2 module for country code lookup. 2023-07-11 00:25:43 +00:00
575b5e8271 Updated info pages. 2023-07-10 23:07:48 +00:00
69d04a7929 Switched to a tools directory for commands. 2023-07-10 22:52:30 +00:00
9cb0a04611 Get rid of unused JSON stuff. 2023-07-10 20:12:20 +00:00
9feb6bcb66 Fixed country name not having a value for XX or any other fallback. 2023-07-05 23:12:44 +00:00
3507ae61ff Switched to Index byte formatter and adjusted max file sizes. 2023-07-05 23:09:28 +00:00
191ef06ef3 Added local country list instead. 2023-07-05 02:23:34 +00:00
027ed5aff6 Cleaned up various utility functions. 2023-07-05 01:33:12 +00:00
1bb9bd6541 Apply user colour to header rather than username on profiles. 2023-07-03 13:53:58 +00:00
b5b4bf6b5a Fixed birthdate setting not working (did it ever work???). 2023-05-26 18:41:21 +00:00
0bb1303413 Updated authentication token format. 2023-05-21 18:15:04 +00:00
5d602bd56f Fixed Insert button for uploads inserting with the wrong markup format if the setting was changed after upload. 2023-05-04 17:20:56 +00:00
8038f61470 Added ability to add redirects to deleted topic ids. 2023-04-30 00:18:14 +00:00
6f679fc78c Fixed oversights that occur because of the empty username. 2023-04-29 21:57:21 +00:00
c06993ff1d Removed space inserted before embed tags inserted by EEPROM. 2023-03-15 10:58:55 +00:00
11ff8b5be1 Removed quirky newline. 2023-03-11 22:28:57 +00:00
d54528f8ea Gave posts a 1 minute cooldown for edits without being marked as edited. 2023-03-11 22:28:10 +00:00
d05046ff1f Removed Twitter integrations. 2023-03-09 21:38:03 +00:00
521a8fb0d1 Added rudimentary EEPROM file uploading support to the forum post editor. 2023-03-09 21:05:37 +00:00
e909b2ffda Added editor buttons for video and audio in markdown mode. 2023-03-09 16:27:43 +00:00
a04df5cb43 Updated composter packages. 2023-03-09 16:23:42 +00:00
9983233184 Allow media linking without https: or http: prefix on forum. 2023-03-09 16:18:52 +00:00
c7ed6ba511 Fixed smart event. 2023-02-24 18:36:32 +00:00
5760e15df5 Added h1 thru h6 bbcodes. 2023-02-12 03:50:08 +00:00
d423c53cde Added most active forum category and topic to profiles. 2023-02-10 09:04:15 +00:00
b9b80e17d0 Sharp Chat interop updates. 2023-02-08 00:06:15 +00:00
18c836a457 Made Twitter and Chat link targets in the header configurable. 2023-01-31 16:21:19 +00:00
af6d4aff3a Forum post text style fixes. 2023-01-29 21:34:22 +00:00
03a0dcd948 Enabled video and audio embeds in markdown. 2023-01-29 21:06:03 +00:00
e6e5c873f6 Audio embed previews (no player yet). 2023-01-29 20:29:20 +00:00
a4be74cae3 constipation moment 2023-01-29 03:35:45 +00:00
e1122fb6b9 Improved video embed handling. 2023-01-29 01:51:54 +00:00
48ce465893 Fixed various video embedding bugs. 2023-01-26 22:51:33 +00:00
9dae77628d Removed will-change statements because buggy in Chrome. 2023-01-26 08:49:19 +00:00
58edc5c5dc Fixed videos not embedding in the posting preview. 2023-01-25 23:03:38 +00:00
d5bb0bb475 Complete revamp of the forum video bbcode.
Rather than blindly embedding everything, video metadata is first requested through the URL metadata lookup service.
This slightly protects you from automatically connecting to third party servers and also vastly improves page loading performance in tandem with caching on the server.
A similar implementation will eventually make its way to the audio bbcode and will also be worked in the img bbcode somehow.
This will then eventually make it possible to embed audio and video in markdown the same way you'd embed an image.
2023-01-25 22:33:59 +00:00
6727abe6c3 Fixed 'view full profile' thing showing up on non-existent users while logged out. 2023-01-07 04:47:31 +00:00
047d225669 Fixed inability to log in with two factor authentication. 2023-01-07 04:46:49 +00:00
37eea64a27 Updated database migration system to use the Index methods. 2023-01-07 04:15:19 +00:00
5a4094867f Use interface constants instead of a dedicate enum class for config types. 2023-01-06 20:50:41 +00:00
5a7f4765ab Changed name of context class and global variable. 2023-01-06 20:35:03 +00:00
e8518fde65 Updated handler classes to use the new IRouter interface. 2023-01-06 20:22:03 +00:00
338945d01e Removed unused tester permission. 2023-01-06 00:03:29 +00:00
56a9192f53 Store forum permission types as numbers rather than bit shifts. 2023-01-06 00:02:40 +00:00
8bb8a6b6a5 Removed error to exception conversion in Misuzu (handled in Index). 2023-01-05 23:54:27 +00:00
a311de6acf Updates to GeoIP lookup stuff. 2023-01-05 20:03:26 +00:00
f168aceb03 Updated composer libraries. 2023-01-05 18:35:07 +00:00
2394492bf8 Remove IPAddress::remote and all implicit resolving of the request remote address. 2023-01-05 18:33:03 +00:00
f7fcd3230a Removed IPAddress methods only used by the blacklist. 2023-01-05 17:15:26 +00:00
05766f00e0 Removed IP blacklist for now. 2023-01-05 15:56:36 +00:00
eafdc28d5e Rewrote Twitter connection (v1.1 -> v2). 2023-01-05 03:20:31 +00:00
cb40fdc7c4 Fixed error when trying to use the forum posting form. 2023-01-03 00:31:39 +00:00
ebabb19998 Rewrote avatar element contruction as Twig macro. 2023-01-03 00:10:28 +00:00
47121897b9 Updated copyright year. 2023-01-02 23:52:40 +00:00
4f3d0c5246 Replaced Misuzu Colour library with the Index ones. 2023-01-02 23:48:04 +00:00
f9d2ca2bb5 Removed more XHR leftovers. 2023-01-02 23:12:23 +00:00
053109fe4f Removed XHR stuff from comments handler. 2023-01-02 22:59:24 +00:00
d9c3ca1e5a "Fixed" user editor in the broom closet. 2023-01-02 20:09:38 +00:00
ed2201090c Pruned a lot of existing Javascript, comments will receive and overhaul later. 2023-01-02 20:07:55 +00:00
5a495ec472 Fixed Mark As Read on forum index not working. 2023-01-02 19:50:33 +00:00
b451e87fa5 Updated contact info. 2023-01-02 18:41:47 +00:00
623 changed files with 35105 additions and 21838 deletions

1
.browserslistrc Normal file
View file

@ -0,0 +1 @@
last 5 versions, not dead

2
.gitattributes vendored
View file

@ -1,3 +1 @@
* text=auto
/msz text eol=lf
*.sh text eol=lf

13
.gitignore vendored
View file

@ -1,15 +1,22 @@
# Assets
/public/assets
/assets/current.json
# Libraries
/vendor
/node_modules
/npm-debug.log
/yarn-error.log
/lib/index-dev
/composer.local.json
# Configuration
/config/config.cfg
/config/github.cfg
/config/config.ini
/config/github.ini
/.debug
/.migrating
/lib/index-dev
# Storage
/store
@ -38,3 +45,7 @@
# Google
/public/robots.txt
# moguu?
/public/moguu.swf
/public/moguu.html

3
.gitmodules vendored
View file

@ -1,3 +0,0 @@
[submodule "lib/index"]
path = lib/index
url = https://git.flash.moe/flash/index.git

221
LICENSE
View file

@ -1,201 +1,30 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright (c) 2017-2024, flashwave <me@flash.moe>
All rights reserved.
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
Redistribution and use in source and binary forms, with or without
modification, are permitted (subject to the limitations in the disclaimer
below) provided that the following conditions are met:
1. Definitions.
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017-2022 flashwave <me@flash.moe>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View file

@ -2,10 +2,6 @@
> Misuzu can and will steal your lunch money.
## Requirements
- PHP 8.1
- PHP 8.2 (64-bit)
- MariaDB 10.6
- [Composer](https://getcomposer.org/)
## Important
DON'T RUN ANYTHING IN THE `devel` FOLDER IN PRODUCTION UNLESS YOU SERIOUSLY WANT TO FUCK EVERYTHING UP.

7
Vagrantfile vendored
View file

@ -1,7 +0,0 @@
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/focal64"
config.vm.network "forwarded_port", guest: 80, host: 10080
config.vm.network "forwarded_port", guest: 443, host: 10443
config.vm.network "forwarded_port", guest: 3306, host: 13306
config.vm.provision :shell, path: "devel/setup-devbox.sh"
end

View file

@ -1,6 +0,0 @@
# Misuzu Assets
Subdirectories of the `css` and `js` folder are accessible through the web as `example.com/assets/<subdirectory>.<directory>`.
Meaning `/assets/js/misuzu` is accessible as `/assets/misuzu.js`.
Files are concatenated recursively, files first then directories in alphabetical order.
Use `_` prefixes to raise things up.

108
assets/assproc.js Normal file
View file

@ -0,0 +1,108 @@
const fs = require('fs');
const path = require('path');
const readline = require('readline');
const utils = require('./utils.js');
exports.process = async function(root, options) {
const macroPrefix = options.prefix || '#';
const entryPoint = options.entry || '';
root = fs.realpathSync(root);
const included = [];
const processFile = async function(fileName) {
const fullPath = path.join(root, fileName);
if(included.includes(fullPath))
return '';
included.push(fullPath);
if(!fullPath.startsWith(root))
return '/* *** INVALID PATH: ' + fullPath + ' */';
if(!fs.existsSync(fullPath))
return '/* *** FILE NOT FOUND: ' + fullPath + ' */';
const lines = readline.createInterface({
input: fs.createReadStream(fullPath),
crlfDelay: Infinity,
});
let output = '';
let lastWasEmpty = false;
if(options.showPath)
output += "/* *** PATH: " + fullPath + " */\n";
for await(const line of lines) {
const lineTrimmed = utils.trim(line);
if(lineTrimmed === '')
continue;
if(line.startsWith(macroPrefix)) {
const args = lineTrimmed.split(' ');
const macro = utils.trim(utils.trimStart(args.shift(), macroPrefix));
switch(macro) {
case 'comment':
break;
case 'include': {
const includePath = utils.trimEnd(args.join(' '), ';');
output += utils.trim(await processFile(includePath));
output += "\n";
break;
}
case 'buildvars':
if(typeof options.buildVars === 'object') {
const bvTarget = options.buildVarsTarget || 'window';
const bvProps = [];
for(const bvName in options.buildVars)
bvProps.push(`${bvName}: { value: ${JSON.stringify(options.buildVars[bvName])}, writable: false }`);
if(Object.keys(bvProps).length > 0)
output += `Object.defineProperties(${bvTarget}, { ${bvProps.join(', ')} });\n`;
}
break;
default:
output += line;
output += "\n";
break;
}
} else {
output += line;
output += "\n";
}
}
return output;
};
return await processFile(entryPoint);
};
exports.housekeep = function(assetsPath) {
const files = fs.readdirSync(assetsPath).map(fileName => {
const stats = fs.statSync(path.join(assetsPath, fileName));
return {
name: fileName,
lastMod: stats.mtimeMs,
};
}).sort((a, b) => b.lastMod - a.lastMod).map(info => info.name);
const regex = /^(.+)[\-\.]([a-f0-9]+)\.(.+)$/i;
const counts = {};
for(const fileName of files) {
const match = fileName.match(regex);
if(match) {
const name = match[1] + '-' + match[3];
counts[name] = (counts[name] || 0) + 1;
if(counts[name] > 5)
fs.unlinkSync(path.join(assetsPath, fileName));
} else console.log(`Encountered file name in assets folder with unexpected format: ${fileName}`);
}
};

View file

@ -1,96 +0,0 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
position: relative;
outline-style: none;
}
html,
body {
width: 100%;
height: 100%;
}
[hidden],
.hidden {
display: none !important;
visibility: hidden !important;
}
:root {
--font-size: 12px;
--line-height: 20px;
--font-regular: Verdana, Geneva, 'Dejavu Sans', Arial, Helvetica, sans-serif;
--font-monospace: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
--site-max-width: 1200px;
--site-mobile-width: 800px;
--site-logo: url('/images/logos/imouto-default.png');
--header-height-desktop: 70px;
--header-height-mobile: 50px;
--background-image: initial;
--background-colour: #111;
--background-colour-translucent-1: rgba(17, 17, 17, 0.1);
--background-colour-translucent-2: rgba(17, 17, 17, 0.2);
--background-colour-translucent-3: rgba(17, 17, 17, 0.3);
--background-colour-translucent-4: rgba(17, 17, 17, 0.4);
--background-colour-translucent-5: rgba(17, 17, 17, 0.5);
--background-colour-translucent-6: rgba(17, 17, 17, 0.6);
--background-colour-translucent-7: rgba(17, 17, 17, 0.7);
--background-colour-translucent-8: rgba(17, 17, 17, 0.8);
--background-colour-translucent-9: rgba(17, 17, 17, 0.9);
--background-pattern: url('/images/clouds.png') fixed;
--container-colour: #161616;
--text-colour: #fff;
--text-colour-inverted: #000;
--user-colour: inherit;
--user-header: url('/images/pixel.png');
--accent-colour: #8559a5;
--header-accent-colour: var(--accent-colour);
}
html {
scrollbar-color: var(--accent-colour) var(--background-colour);
}
.main {
display: flex;
flex-direction: column;
background-image: var(--background-image);
background-color: var(--background-colour);
font-size: var(--font-size);
line-height: var(--line-height);
font-family: var(--font-regular);
color: var(--text-colour);
background-attachment: fixed;
background-position: center center;
}
.main__wrapper {
max-width: var(--site-max-width);
width: 100%;
margin: 0 auto;
flex: 1 0 auto;
}
.main--bg-blend {
background-color: var(--accent-colour);
background-blend-mode: multiply;
}
.main--bg-slide { animation: background-slide infinite linear 2s; }
.main--bg-cover { background-size: cover; }
.main--bg-contain { background-size: contain; }
.main--bg-stretch { background-size: 100% 100%; }
.main--bg-tile { background-size: auto; }
.link {
color: var(--accent-colour);
text-decoration: none;
}
.link:hover, .link:focus { text-decoration: underline; }

View file

@ -1,25 +0,0 @@
.manage {
display: flex;
}
.manage__sidebar {
flex: 0 0 auto;
width: 280px;
}
.manage__content {
flex: 1 1 auto;
}
.manage__description {
font-size: .9em;
margin: 1px 2px;
border-bottom: 1px solid var(--accent-colour);
padding: 2px 5px;
}
@media (max-width: 800px) {
.manage {
flex-direction: column;
}
.manage__sidebar {
width: 100%;
}
}

View file

@ -1,129 +0,0 @@
.news__preview {
display: flex;
margin: 2px 0;
flex-direction: row-reverse;
--user-colour: var(--accent-colour);
}
.news__preview__info__content {
width: 200px;
text-align: center;
display: flex;
flex-direction: column;
padding: 15px;
flex: 0 0 auto;
margin-right: 4px;
}
.news__preview__info__background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
mask-image: linear-gradient(90deg, transparent 10%, var(--background-colour) 100%);
-webkit-mask-image: linear-gradient(90deg, transparent 10%, var(--background-colour) 100%);
background: var(--background-pattern);
background-color: var(--user-colour);
background-blend-mode: multiply;
}
.news__preview__listing {
flex-grow: 1;
flex-shrink: 1;
}
.news__preview__container {
display: flex;
margin: 1px;
flex-direction: column;
}
.news__preview__user {
display: flex;
text-align: left;
align-items: center;
margin-bottom: 10px;
}
.news__preview__user__details {
display: flex;
flex-direction: column;
}
.news__preview__avatar {
width: 60px;
height: 60px;
margin-right: 10px;
}
.news__preview__username {
color: inherit;
font-size: 1.4em;
line-height: 1.5em;
text-decoration: none;
}
.news__preview__username[href]:hover {
text-decoration: underline;
}
.news__preview__date {
font-size: 1.1em;
line-height: 1.5em;
}
.news__preview__category {
color: inherit;
text-decoration: none;
font-size: 1.1em;
line-height: 1.5em;
margin: 6px 0;
}
.news__preview__category:hover {
text-decoration: underline;
}
.news__preview__content {
display: flex;
flex-direction: column;
line-height: 1.2em;
flex: 1 1 auto;
word-wrap: break-word;
overflow: hidden;
margin: 2px;
padding: 0 10px 10px 10px;
}
.news__preview__text {
flex: 1 1 auto;
}
.news__preview__links {
display: flex;
justify-content: space-between;
}
.news__preview__link {
font-size: .9em;
}
@media (max-width: 800px) {
.news__preview { flex-direction: column-reverse; }
.news__preview__info { display: none; }
.news__preview__info__content {
width: 100%;
flex-wrap: wrap;
text-align: left;
}
.news__preview__info__background {
mask-image: linear-gradient(180deg, transparent 10%, var(--background-colour) 100%);
-webkit-mask-image: linear-gradient(180deg, transparent 10%, var(--background-colour) 100%);
}
.news__preview__user {
margin-bottom: 0;
margin-right: 10px;
}
.news__preview__avatar {
width: 50px;
height: 50px;
}
}

View file

@ -1,10 +0,0 @@
.profile__relations {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.profile__relations__user {
margin: 2px;
width: 300px;
display: flex;
}

View file

@ -1,139 +0,0 @@
.profile__warning {
margin: 2px;
border-radius: 2px;
border: 1px solid var(--accent-colour);
}
.profile__warning__container {
margin: 2px 0;
}
.profile__warning--warning {
--accent-colour: #666;
}
.profile__warning--silence {
--accent-colour: #f70;
}
.profile__warning--ban {
--accent-colour: #c33;
}
.profile__warning--extendo {
margin: 4px;
}
.profile__warning__background {
background-color: var(--accent-colour);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.profile__warning__content {
background-color: var(--background-colour-translucent-9);
display: flex;
padding: 1px;
}
.profile__warning__type,
.profile__warning__created,
.profile__warning__duration {
display: inline-flex;
align-items: center;
justify-content: center;
}
.profile__warning__type {
min-width: 80px;
background-color: var(--accent-colour);
border-radius: 1px;
padding: 0 4px;
}
.profile__warning__created,
.profile__warning__duration {
min-width: 100px;
padding: 0 4px;
}
.profile__warning__note {
padding: 1px 4px;
flex: 1 1 auto;
}
.profile__warning__private {
border-top: 1px solid var(--accent-colour);
margin-top: 1px;
width: 100%;
opacity: .5;
transition: opacity .2s;
}
.profile__warning__private:hover,
.profile__warning__private:active,
.profile__warning__private:focus {
opacity: 1;
}
.profile__warning__tools {
display: flex;
padding-bottom: 1px;
}
.profile__warning__options {
flex: 1 1 auto;
display: flex;
justify-content: flex-end;
align-items: center;
}
.profile__warning__option {
padding: 2px 5px;
color: inherit;
text-decoration: none;
}
.profile__warning__user {
display: flex;
padding: 2px;
min-width: 300px;
}
.profile__warning__user__avatar {
width: 20px;
height: 20px;
}
.profile__warning__user__username {
padding: 0 5px;
min-width: 60px;
color: inherit;
text-decoration: none;
}
.profile__warning__user__username:hover,
.profile__warning__user__username:focus,
.profile__warning__user__username:active {
text-decoration: underline;
}
.profile__warning__user__ip {
display: inline-flex;
padding: 0 5px;
}
.profile__warning__user__ip:before { content: "("; }
.profile__warning__user__ip:after { content: ")"; }
@media (max-width: 800px) {
.profile__warning__content {
flex-wrap: wrap;
}
.profile__warning__tools {
flex-direction: column;
}
.profile__warning__options {
justify-content: flex-start;
}
}

View file

@ -1,170 +0,0 @@
.usercard {
display: flex;
flex-direction: column;
transition: box-shadow .5s;
z-index: 1;
color: #fff;
background-color: var(--background-colour);
box-shadow: 0 1px 2px #000A;
text-shadow: 0 1px 4px #000;
overflow: hidden;
flex: 1 1 auto;
--usercard-header-overlay-start: transparent;
--usercard-header-overlay-stop: var(--background-colour-translucent-9);
}
.usercard:hover {
box-shadow: 0 1px 4px #000;
z-index: 2;
}
.usercard__background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--accent-colour) var(--background-pattern);
background-blend-mode: multiply;
}
.usercard__header {
flex: 0 0 auto;
}
.usercard__header__link {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.usercard__header__avatar {
width: 60px;
height: 60px;
z-index: 20;
}
.usercard__header__container {
display: flex;
align-items: center;
padding: 10px;
background-image: linear-gradient(0deg, var(--usercard-header-overlay-stop), var(--usercard-header-overlay-start));
pointer-events: none;
}
.usercard__header__details {
margin: 0 10px;
flex: 1 1 auto;
}
.usercard__header__relation {
font-variant: all-small-caps;
background: var(--usercard-header-overlay-stop);
border-radius: 2px;
line-height: 1.2em;
padding: 1px 5px 4px;
cursor: default;
}
.usercard__header__username {
font-size: 1.5em;
line-height: 1.3em;
}
.usercard__header__title {
font-size: .9em;
line-height: 1.2em;
}
.usercard__header__country {
display: inline-flex;
align-items: center;
}
.usercard__header__country__name {
font-size: .9em;
margin-left: 4px;
line-height: 1.2em;
}
.usercard__container {
flex: 1 1 auto;
background-color: var(--usercard-header-overlay-stop);
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.usercard__dates {
font-size: .9em;
line-height: 1em;
display: flex;
justify-content: space-evenly;
align-items: center;
flex: 0 0 auto;
margin-bottom: 4px;
}
.usercard__date {
padding: 4px;
}
.usercard__stats {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
flex: 0 0 auto;
}
.usercard__stat {
display: flex;
flex-direction: column-reverse;
color: inherit;
text-decoration: none;
padding: 5px 10px;
cursor: default;
flex: 0 0 auto;
text-align: right;
}
.usercard__stat[href] {
cursor: pointer;
}
.usercard__stat[href]:hover,
.usercard__stat[href]:focus {
border-bottom: 2px solid var(--accent-colour);
padding-bottom: 3px;
}
.usercard__stat__name {
font-size: .9em;
font-variant: small-caps;
cursor: inherit;
}
.usercard__stat__value {
font-size: 1.3em;
cursor: inherit;
display: block;
}
.usercard__actions {
flex: 0 0 auto;
display: flex;
height: 38px;
}
.usercard__action {
flex: 1 1 auto;
display: flex;
justify-content: center;
align-items: center;
color: inherit;
text-decoration: none;
font-size: 1.5em;
transition: background-color .2s;
text-align: center;
cursor: pointer;
}
.usercard__action:hover,
.usercard__action:focus { background-color: rgba(255, 255, 255, .2); }
.usercard__action:active { background-color: rgba(255, 255, 255, .1); }
@media (max-width: 800px) {
.usercard__header__details {
text-align: center;
}
}

View file

@ -1,176 +0,0 @@
Array.prototype.removeIndex = function(index) {
this.splice(index, 1);
return this;
};
Array.prototype.removeItem = function(item) {
var index;
while(this.length > 0 && (index = this.indexOf(item)) >= 0)
this.removeIndex(index);
return this;
};
Array.prototype.removeFind = function(predicate) {
var index;
while(this.length > 0 && (index = this.findIndex(predicate)) >= 0)
this.removeIndex(index);
return this;
};
HTMLCollection.prototype.toArray = function() {
return Array.prototype.slice.call(this);
};
HTMLTextAreaElement.prototype.insertTags = function(tagOpen, tagClose) {
tagOpen = tagOpen || '';
tagClose = tagClose || '';
if(document.selection) {
this.focus();
var selected = document.selection.createRange();
selected.text = tagOpen + selected.text + tagClose;
this.focus();
} else if(this.selectionStart || this.selectionStart === 0) {
var startPos = this.selectionStart,
endPos = this.selectionEnd,
scrollTop = this.scrollTop;
this.value = this.value.substring(0, startPos)
+ tagOpen
+ this.value.substring(startPos, endPos)
+ tagClose
+ this.value.substring(endPos, this.value.length);
this.focus();
this.selectionStart = startPos + tagOpen.length;
this.selectionEnd = endPos + tagOpen.length;
this.scrollTop + scrollTop;
} else {
this.value += tagOpen + tagClose;
this.focus();
}
};
var CreateElement = function(elemInfo) {
elemInfo = elemInfo || {};
var elem = document.createElement(elemInfo.tag || 'div');
if(elemInfo.props) {
var propKeys = Object.keys(elemInfo.props);
for(var i = 0; i < propKeys.length; i++) {
var propKey = propKeys[i];
if(elemInfo.props[propKey] === undefined
|| elemInfo.props[propKey] === null)
continue;
switch(typeof elemInfo.props[propKey]) {
case 'function':
elem.addEventListener(
propKey.substring(0, 2) === 'on'
? propKey.substring(2).toLowerCase()
: propKey,
elemInfo.props[propKey]
);
break;
default:
elem.setAttribute(propKey === 'className' ? 'class' : propKey, elemInfo.props[propKey]);
break;
}
}
}
if(elemInfo.children) {
var children = elemInfo.children;
if(!Array.isArray(children))
children = [children];
for(var i = 0; i < children.length; i++) {
var child = children[i];
switch(typeof child) {
case 'string':
elem.appendChild(document.createTextNode(child));
break;
case 'object':
if(child instanceof Element)
elem.appendChild(child);
else if(child.getElement)
elem.appendChild(child.getElement());
else
elem.appendChild(CreateElement(child));
break;
default:
elem.appendChild(document.createTextNode(child.toString()));
break;
}
}
}
if(elemInfo.created)
elemInfo.created(elem);
return elem;
};
var CreateBasicElement = function(className, children, tagName) {
return CreateElement({
tag: tagName || null,
props: {
'class': className || null,
},
'children': children || null,
});
};
var LoadScript = function(url, loaded, error) {
if(document.querySelector('script[src="' + encodeURI(url) + '"]')) {
if(loaded)
loaded();
return;
}
var script = document.createElement('script');
script.type = 'text/javascript';
if(loaded)
script.addEventListener('load', function() { loaded(); });
script.addEventListener('error', function() {
document.body.removeChild(script);
if(error)
error();
});
script.src = url;
document.body.appendChild(script);
};
var MakeEventTarget = function(object) {
object.eventListeners = {};
object.addEventListener = function(type, callback) {
if(!(type in this.eventListeners))
this.eventListeners[type] = [];
this.eventListeners[type].push(callback);
};
object.removeEventListener = function(type, callback) {
if(!(type in this.eventListeners))
return;
this.eventListeners[type].removeItem(callback);
};
object.dispatchEvent = function(event) {
if(!(event.type in this.eventListeners))
return true;
var stack = this.eventListeners[event.type].slice();
for(var i = 0; i < stack.length; ++i)
stack[i].call(this, event);
return !event.defaultPrevented;
};
};
var DefineEnum = function(values) {
var keys = Object.keys(values);
for(var i = 0; i < keys.length; ++i)
values[values[keys[i]]] = keys[i];
return values;
};

View file

@ -1,155 +0,0 @@
var Misuzu = function() {
if(Misuzu.initialised)
throw 'Misuzu script has already initialised.';
Misuzu.started = true;
console.log(
"%cMisuzu%c\nhttps://git.flash.moe/flashii/misuzu",
'font-size: 48px; color: #8559a5; background: #111;'
+ 'border-radius: 5px; padding: 0 10px; text-shadow: 0 0 1em #fff;',
);
timeago.render(document.querySelectorAll('time'));
hljs.initHighlighting();
Misuzu.CSRF.init();
Misuzu.Urls.loadFromDocument();
Misuzu.User.refreshLocalUser();
Misuzu.FormUtils.initDataRequestMethod();
Misuzu.initQuickSubmit();
Misuzu.Comments.init();
Misuzu.Forum.Editor.init();
if(Misuzu.User.isLoggedIn())
console.log(
'You are %s with user id %d and colour %s.',
Misuzu.User.localUser.getUsername(),
Misuzu.User.localUser.getId(),
Misuzu.User.localUser.getColour().getCSS()
);
else
console.log('You aren\'t logged in.');
Misuzu.Events.dispatch();
Misuzu.initLoginPage();
};
Misuzu.Parser = DefineEnum({
plain: 0,
bbcode: 1,
markdown: 2,
});
Misuzu.supportsSidewaysText = function() { return CSS.supports('writing-mode', 'sideways-lr'); };
Misuzu.showMessageBox = function(text, title, buttons) {
if(document.querySelector('.messagebox'))
return false;
text = text || '';
title = title || '';
buttons = buttons || [];
var element = document.createElement('div');
element.className = 'messagebox';
var container = element.appendChild(document.createElement('div'));
container.className = 'container messagebox__container';
var titleElement = container.appendChild(document.createElement('div')),
titleBackground = titleElement.appendChild(document.createElement('div')),
titleText = titleElement.appendChild(document.createElement('div'));
titleElement.className = 'container__title';
titleBackground.className = 'container__title__background';
titleText.className = 'container__title__text';
titleText.textContent = title || 'Information';
var textElement = container.appendChild(document.createElement('div'));
textElement.className = 'container__content';
textElement.textContent = text;
var buttonsContainer = container.appendChild(document.createElement('div'));
buttonsContainer.className = 'messagebox__buttons';
var firstButton = null;
if(buttons.length < 1) {
firstButton = buttonsContainer.appendChild(document.createElement('button'));
firstButton.className = 'input__button';
firstButton.textContent = 'OK';
firstButton.addEventListener('click', function() { element.remove(); });
} else {
for(var i = 0; i < buttons.length; i++) {
var button = buttonsContainer.appendChild(document.createElement('button'));
button.className = 'input__button';
button.textContent = buttons[i].text;
button.addEventListener('click', function() {
element.remove();
buttons[i].callback();
});
if(firstButton === null)
firstButton = button;
}
}
document.body.appendChild(element);
firstButton.focus();
return true;
};
Misuzu.initLoginPage = function() {
var updateForm = function(avatarElem, usernameElem) {
var xhr = new XMLHttpRequest;
xhr.addEventListener('readystatechange', function() {
if(xhr.readyState !== 4)
return;
var json = JSON.parse(xhr.responseText);
if(!json)
return;
if(json.name)
usernameElem.value = json.name;
avatarElem.src = json.avatar;
});
xhr.open('GET', Misuzu.Urls.format('auth-resolve-user', [{name: 'username', value: encodeURIComponent(usernameElem.value)}]));
xhr.send();
};
var loginForms = document.getElementsByClassName('js-login-form');
for(var i = 0; i < loginForms.length; ++i)
(function(form) {
var loginTimeOut = 0,
loginAvatar = form.querySelector('.js-login-avatar'),
loginUsername = form.querySelector('.js-login-username');
updateForm(loginAvatar, loginUsername);
loginUsername.addEventListener('keyup', function() {
if(loginTimeOut)
return;
loginTimeOut = setTimeout(function() {
updateForm(loginAvatar, loginUsername);
clearTimeout(loginTimeOut);
loginTimeOut = 0;
}, 750);
});
})(loginForms[i]);
};
Misuzu.initQuickSubmit = function() {
var ctrlSubmit = document.getElementsByClassName('js-quick-submit').toArray().concat(document.getElementsByClassName('js-ctrl-enter-submit').toArray());
if(!ctrlSubmit)
return;
for(var i = 0; i < ctrlSubmit.length; ++i)
ctrlSubmit[i].addEventListener('keydown', function(ev) {
if((ev.code === 'Enter' || ev.code === 'NumpadEnter') // i hate this fucking language so much
&& ev.ctrlKey && !ev.altKey && !ev.shiftKey && !ev.metaKey) {
// hack: prevent forum editor from screaming when using this keycombo
// can probably be done in a less stupid manner
Misuzu.Forum.Editor.allowWindowClose = true;
this.form.submit();
ev.preventDefault();
}
});
};

View file

@ -1,93 +0,0 @@
Misuzu.Colour = function(raw) {
this.setRaw(raw || 0);
};
Misuzu.Colour.prototype.raw = 0;
Misuzu.Colour.FLAG_INHERIT = 0x40000000;
Misuzu.Colour.READABILITY_THRESHOLD = 186;
Misuzu.Colour.LUMINANCE_WEIGHT_RED = .299;
Misuzu.Colour.LUMINANCE_WEIGHT_GREEN = .587;
Misuzu.Colour.LUMINANCE_WEIGHT_BLUE = .114;
Misuzu.Colour.none = function() { return new Misuzu.Colour(Misuzu.Colour.FLAG_INHERIT); };
Misuzu.Colour.fromRGB = function(red, green, blue) {
var colour = new Misuzu.Colour;
colour.setRed(red);
colour.setGreen(green);
colour.setBlue(blue);
return colour;
};
Misuzu.Colour.fromHex = function(hex) {
var colour = new Misuzu.Colour;
colour.setHex(hex);
return colour;
};
Misuzu.Colour.prototype.getRaw = function() { return this.raw; };
Misuzu.Colour.prototype.setRaw = function(raw) {
this.raw = parseInt(raw) & 0x7FFFFFFF;
};
Misuzu.Colour.prototype.getInherit = function() { return (this.getRaw() & Misuzu.Colour.FLAG_INHERIT) > 0; };
Misuzu.Colour.prototype.setInherit = function(inherit) {
var raw = this.getRaw();
if(inherit)
raw |= Misuzu.Colour.FLAG_INHERIT;
else
raw &= ~Misuzu.Colour.FLAG_INHERIT;
this.setRaw(raw);
};
Misuzu.Colour.prototype.getRed = function() { return (this.getRaw() >> 16) & 0xFF };
Misuzu.Colour.prototype.setRed = function(red) {
var raw = this.getRaw();
raw &= ~0xFF0000;
raw |= (parseInt(red) & 0xFF) << 16;
this.setRaw(raw);
};
Misuzu.Colour.prototype.getGreen = function() { return (this.getRaw() >> 8) & 0xFF };
Misuzu.Colour.prototype.setGreen = function(green) {
var raw = this.getRaw();
raw &= ~0xFF0000;
raw |= (parseInt(green) & 0xFF) << 8;
this.setRaw(raw);
};
Misuzu.Colour.prototype.getBlue = function() { return this.getRaw() & 0xFF };
Misuzu.Colour.prototype.setBlue = function(blue) {
var raw = this.getRaw();
raw &= ~0xFF0000;
raw |= parseInt(blue) & 0xFF;
this.setRaw(raw);
};
Misuzu.Colour.prototype.getLuminance = function() {
return Misuzu.Colour.LUMINANCE_WEIGHT_RED * this.getRed()
+ Misuzu.Colour.LUMINANCE_WEIGHT_GREEN * this.getGreen()
+ Misuzu.Colour.LUMINANCE_WEIGHT_BLUE * this.getBlue();
};
Misuzu.Colour.prototype.getHex = function() {
var hex = (this.getRaw() & 0xFFFFFF).toString(16);
if(hex.length < 6)
hex = '000000'.substring(0, 6 - hex.length) + hex;
return hex;
};
Misuzu.Colour.prototype.setHex = function(hex) {
hex = (hex || '').toString();
if(hex[0] === '#')
hex = hex.substring(1);
if(/[^A-Fa-f0-9]/g.test(hex))
throw 'Argument contains invalid characters.';
if(hex.length === 3)
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
else if(hex.length !== 6)
throw 'Argument is not a hex string.';
return this.setRaw(parseInt(hex, 16));
};
Misuzu.Colour.prototype.getCSS = function() {
if(this.getInherit())
return 'inherit';
return '#' + this.getHex();
};
Misuzu.Colour.prototype.getCSSConstrast = function(dark, light, inheritIsDark) {
dark = dark || 'dark';
light = light || 'light';
if(this.getInherit())
return inheritIsDark ? dark : light;
return this.getLuminance() > Misuzu.Colour.READABILITY_THRESHOLD ? dark : light;
};

View file

@ -1,491 +0,0 @@
Misuzu.Comments = {};
Misuzu.Comments.Vote = DefineEnum({
none: 0,
like: 1,
dislike: -1,
});
Misuzu.Comments.init = function() {
var commentDeletes = document.getElementsByClassName('comment__action--delete');
for(var i = 0; i < commentDeletes.length; ++i) {
commentDeletes[i].addEventListener('click', Misuzu.Comments.deleteCommentHandler);
commentDeletes[i].dataset.href = commentDeletes[i].href;
commentDeletes[i].href = 'javascript:;';
}
var commentInputs = document.getElementsByClassName('comment__text--input');
for(var i = 0; i < commentInputs.length; ++i) {
commentInputs[i].form.action = 'javascript:void(0);';
commentInputs[i].form.addEventListener('submit', Misuzu.Comments.postCommentHandler);
commentInputs[i].addEventListener('keydown', Misuzu.Comments.inputCommentHandler);
}
var voteButtons = document.getElementsByClassName('comment__action--vote');
for(var i = 0; i < voteButtons.length; ++i) {
voteButtons[i].href = 'javascript:;';
voteButtons[i].addEventListener('click', Misuzu.Comments.voteCommentHandler);
}
var pinButtons = document.getElementsByClassName('comment__action--pin');
for(var i = 0; i < pinButtons.length; ++i) {
pinButtons[i].href = 'javascript:;';
pinButtons[i].addEventListener('click', Misuzu.Comments.pinCommentHandler);
}
};
Misuzu.Comments.postComment = function(formData, onSuccess, onFailure) {
if(!Misuzu.User.isLoggedIn()
|| !Misuzu.User.localUser.perms.canCreateComment()) {
if(onFailure)
onFailure("You aren't allowed to post comments.");
return;
}
var xhr = new XMLHttpRequest;
xhr.addEventListener('readystatechange', function() {
if(xhr.readyState !== 4)
return;
Misuzu.CSRF.setToken(xhr.getResponseHeader('X-Misuzu-CSRF'));
var json = JSON.parse(xhr.responseText),
message = json.error || json.message;
if(message && onFailure)
onFailure(message);
else if(!message && onSuccess)
onSuccess(json);
});
xhr.open('POST', Misuzu.Urls.format('comment-create'));
xhr.setRequestHeader('X-Misuzu-XHR', 'comments');
xhr.send(formData);
};
Misuzu.Comments.postCommentHandler = function() {
if(this.dataset.disabled)
return;
this.dataset.disabled = '1';
this.style.opacity = '0.5';
Misuzu.Comments.postComment(
Misuzu.FormUtils.extractFormData(this, true),
Misuzu.Comments.postCommentSuccess.bind(this),
Misuzu.Comments.postCommentFailed.bind(this)
);
};
Misuzu.Comments.inputCommentHandler = function(ev) {
if(ev.code === 'Enter' && ev.ctrlKey && !ev.altKey && !ev.shiftKey && !ev.metaKey) {
Misuzu.Comments.postComment(
Misuzu.FormUtils.extractFormData(this.form, true),
Misuzu.Comments.postCommentSuccess.bind(this.form),
Misuzu.Comments.postCommentFailed.bind(this.form)
);
}
};
Misuzu.Comments.postCommentSuccess = function(comment) {
if(this.classList.contains('comment--reply'))
this.parentNode.parentNode.querySelector('label.comment__action').click();
Misuzu.Comments.insertComment(comment, this);
this.style.opacity = '1';
this.dataset.disabled = '';
};
Misuzu.Comments.postCommentFailed = function(message) {
Misuzu.showMessageBox(message);
this.style.opacity = '1';
this.dataset.disabled = '';
};
Misuzu.Comments.deleteComment = function(commentId, onSuccess, onFailure) {
if(!Misuzu.User.isLoggedIn()
|| !Misuzu.User.localUser.perms.canDeleteOwnComment()) {
if(onFailure)
onFailure('You aren\'t allowed to delete comments.');
return;
}
var xhr = new XMLHttpRequest;
xhr.addEventListener('readystatechange', function() {
if(xhr.readyState !== 4)
return;
Misuzu.CSRF.setToken(xhr.getResponseHeader('X-Misuzu-CSRF'));
var json = JSON.parse(xhr.responseText),
message = json.error || json.message;
if(message && onFailure)
onFailure(message);
else if(!message && onSuccess)
onSuccess(json);
});
xhr.open('GET', Misuzu.Urls.format('comment-delete', [Misuzu.Urls.v('comment', commentId)]));
xhr.setRequestHeader('X-Misuzu-XHR', 'comments');
xhr.send();
};
Misuzu.Comments.deleteCommentHandler = function() {
var commentId = parseInt(this.dataset.commentId);
if(commentId < 1)
return;
Misuzu.Comments.deleteComment(
commentId,
function(info) {
var elem = document.getElementById('comment-' + info.id);
if(elem)
elem.parentNode.removeChild(elem);
},
function(message) { Misuzu.showMessageBox(message); }
);
};
Misuzu.Comments.pinComment = function(commentId, pin, onSuccess, onFailure) {
if(!Misuzu.User.isLoggedIn()
|| !Misuzu.User.localUser.perms.canPinComment()) {
if(onFailure)
onFailure("You aren't allowed to pin comments.");
return;
}
var xhr = new XMLHttpRequest;
xhr.onreadystatechange = function() {
if(xhr.readyState !== 4)
return;
Misuzu.CSRF.setToken(xhr.getResponseHeader('X-Misuzu-CSRF'));
var json = JSON.parse(xhr.responseText),
message = json.error || json.message;
if(message && onFailure)
onFailure(message);
else if(!message && onSuccess)
onSuccess(json);
};
xhr.open('GET', Misuzu.Urls.format('comment-' + (pin ? 'pin' : 'unpin'), [Misuzu.Urls.v('comment', commentId)]));
xhr.setRequestHeader('X-Misuzu-XHR', 'comments');
xhr.send();
};
Misuzu.Comments.pinCommentHandler = function() {
var target = this,
commentId = parseInt(target.dataset.commentId),
isPinned = target.dataset.commentPinned !== '0';
target.textContent = '...';
Misuzu.Comments.pinComment(
commentId,
!isPinned,
function(info) {
if(info.comment_pinned === null) {
target.textContent = 'Pin';
target.dataset.commentPinned = '0';
var pinElement = document.querySelector('#comment-' + info.comment_id + ' .comment__pin');
pinElement.parentElement.removeChild(pinElement);
} else {
target.textContent = 'Unpin';
target.dataset.commentPinned = '1';
var pinInfo = document.querySelector('#comment-' + info.comment_id + ' .comment__info'),
pinElement = document.createElement('div'),
pinTime = document.createElement('time'),
pinDateTime = new Date(info.comment_pinned + 'Z');
pinTime.title = pinDateTime.toLocaleString();
pinTime.dateTime = pinDateTime.toISOString();
pinTime.textContent = timeago.format(pinDateTime);
timeago.render(pinTime);
pinElement.className = 'comment__pin';
pinElement.appendChild(document.createTextNode('Pinned '));
pinElement.appendChild(pinTime);
pinInfo.appendChild(pinElement);
}
},
function(message) {
target.textContent = isPinned ? 'Unpin' : 'Pin';
Misuzu.showMessageBox(message);
}
);
};
Misuzu.Comments.voteComment = function(commentId, vote, onSuccess, onFailure) {
if(!Misuzu.User.isLoggedIn()
|| !Misuzu.User.localUser.perms.canVoteOnComment()) {
if(onFailure)
onFailure("You aren't allowed to vote on comments.");
return;
}
var xhr = new XMLHttpRequest;
xhr.onreadystatechange = function() {
if(xhr.readyState !== 4)
return;
Misuzu.CSRF.setToken(xhr.getResponseHeader('X-Misuzu-CSRF'));
var json = JSON.parse(xhr.responseText),
message = json.error || json.message;
if(message && onFailure)
onFailure(message);
else if(!message && onSuccess)
onSuccess(json);
};
xhr.open('GET', Misuzu.Urls.format('comment-vote', [Misuzu.Urls.v('comment', commentId), Misuzu.Urls.v('vote', vote)]));
xhr.setRequestHeader('X-Misuzu-XHR', 'comments');
xhr.send();
};
Misuzu.Comments.voteCommentHandler = function() {
var commentId = parseInt(this.dataset.commentId),
voteType = parseInt(this.dataset.commentVote),
buttons = document.querySelectorAll('.comment__action--vote[data-comment-id="' + commentId + '"]'),
likeButton = document.querySelector('.comment__action--like[data-comment-id="' + commentId + '"]'),
dislikeButton = document.querySelector('.comment__action--dislike[data-comment-id="' + commentId + '"]'),
classVoted = 'comment__action--voted';
for(var i = 0; i < buttons.length; ++i) {
buttons[i].textContent = buttons[i] === this ? '...' : '';
buttons[i].classList.remove(classVoted);
buttons[i].dataset.commentVote = buttons[i] === likeButton
? (voteType === Misuzu.Comments.Vote.like ? Misuzu.Comments.Vote.none : Misuzu.Comments.Vote.like ).toString()
: (voteType === Misuzu.Comments.Vote.dislike ? Misuzu.Comments.Vote.none : Misuzu.Comments.Vote.dislike).toString();
}
Misuzu.Comments.voteComment(
commentId,
voteType,
function(info) {
switch(voteType) {
case Misuzu.Comments.Vote.like:
likeButton.classList.add(classVoted);
break;
case Misuzu.Comments.Vote.dislike:
dislikeButton.classList.add(classVoted);
break;
}
likeButton.textContent = info.likes > 0 ? ('Like (' + info.likes.toLocaleString() + ')') : 'Like';
dislikeButton.textContent = info.dislikes > 0 ? ('Dislike (' + info.dislikes.toLocaleString() + ')') : 'Dislike';
},
function(message) {
likeButton.textContent = 'Like';
dislikeButton.textContent = 'Dislike';
Misuzu.showMessageBox(message);
}
);
};
Misuzu.Comments.insertComment = function(comment, form) {
var isReply = form.classList.contains('comment--reply'),
parent = isReply
? form.parentElement
: form.parentElement.parentElement.getElementsByClassName('comments__listing')[0],
repliesIndent = isReply
? (parseInt(parent.classList[1].substr(25)) + 1)
: 1,
commentElement = Misuzu.Comments.buildComment(comment, repliesIndent);
if(isReply)
parent.appendChild(commentElement);
else
parent.insertBefore(commentElement, parent.firstElementChild);
var placeholder = document.getElementById('_no_comments_notice_' + comment.category_id);
if(placeholder)
placeholder.parentNode.removeChild(placeholder);
};
Misuzu.Comments.buildComment = function(comment, layer) {
comment = comment || {};
layer = parseInt(layer || 0);
var date = new Date(comment.comment_created + 'Z'),
colour = new Misuzu.Colour(comment.user_colour),
actions = [],
commentTime = CreateElement({
tag: 'time',
props: {
className: 'comment__date',
title: date.toLocaleString(),
datetime: date.toISOString(),
},
children: timeago.format(date),
});
if(Misuzu.User.isLoggedIn() && Misuzu.User.localUser.perms.canVoteOnComment()) {
actions.push(CreateElement({
tag: 'a',
props: {
className: 'comment__action comment__action--link comment__action--vote comment__action--like',
'data-comment-id': comment.comment_id,
'data-comment-vote': Misuzu.Comments.Vote.like,
href: 'javascript:;',
onclick: Misuzu.Comments.voteCommentHandler,
},
children: 'Like',
}));
actions.push(CreateElement({
tag: 'a',
props: {
className: 'comment__action comment__action--link comment__action--vote comment__action--dislike',
'data-comment-id': comment.comment_id,
'data-comment-vote': Misuzu.Comments.Vote.dislike,
href: 'javascript:;',
onclick: Misuzu.Comments.voteCommentHandler,
},
children: 'Dislike',
}));
}
actions.push(CreateElement({
tag: 'label',
props: {
className: 'comment__action comment__action--link',
'for': 'comment-reply-toggle-' + comment.comment_id.toString()
},
children: 'Reply',
}));
var commentText = CreateBasicElement('comment__text');
if(comment.comment_html)
commentText.innerHTML = comment.comment_html;
else
commentText.textContent = comment.comment_text;
var commentElem = CreateElement({
props: {
className: 'comment',
id: 'comment-' + comment.comment_id.toString(),
},
children: [
{
props: { className: 'comment__container', },
children: [
{
tag: 'a',
props: {
className: 'comment__avatar',
href: Misuzu.Urls.format('user-profile', [{name:'user',value:comment.user_id}]),
},
children: {
tag: 'img',
props: {
className: 'avatar',
alt: comment.username,
width: (layer <= 1 ? 50 : 40),
height: (layer <= 1 ? 50 : 40),
src: Misuzu.Urls.format('user-avatar', [
{ name: 'user', value: comment.user_id },
{ name: 'res', value: layer <= 1 ? 100 : 80 }
]),
},
},
},
{
props: { className: 'comment__content', },
children: [
{
props: { className: 'comment__info', },
children: [
{
tag: 'a',
props: {
className: 'comment__user comment__user--link',
href: Misuzu.Urls.format('user-profile', [{name:'user',value:comment.user_id}]),
style: '--user-colour: ' + colour.getCSS(),
},
children: comment.username,
},
{
tag: 'a',
props: {
className: 'comment__link',
href: '#comment-' + comment.comment_id.toString(),
},
children: commentTime,
},
],
},
commentText,
{
props: { className: 'comment__actions', },
children: actions,
},
],
},
],
},
{
props: {
className: 'comment__replies comment__replies--indent-' + layer.toString(),
id: 'comment-' + comment.comment_id.toString() + '-replies',
},
children: [
{
tag: 'input',
props: {
className: 'comment__reply-toggle',
type: 'checkbox',
id: ('comment-reply-toggle-' + comment.comment_id.toString()),
},
},
{
tag: 'form',
props: {
className: 'comment comment--input comment--reply',
id: 'comment-reply-' + comment.comment_id.toString(),
method: 'post',
action: 'javascript:;',
onsubmit: Misuzu.Comments.postCommentHandler,
},
children: [
{ tag: 'input', props: { type: 'hidden', name: 'csrf', value: Misuzu.CSRF.getToken() } },
{ tag: 'input', props: { type: 'hidden', name: 'comment[category]', value: comment.category_id } },
{ tag: 'input', props: { type: 'hidden', name: 'comment[reply]', value: comment.comment_id } },
{
props: { className: 'comment__container' },
children: [
{
props: { className: 'avatar comment__avatar' },
children: {
tag: 'img',
props: {
className: 'avatar',
width: 40,
height: 40,
src: Misuzu.Urls.format('user-avatar', [{name: 'user', value: comment.user_id}, {name: 'res', value: 80}]),
},
},
},
{
props: { className: 'comment__content' },
children: [
{ props: { className: 'comment__info' } },
{
tag: 'textarea',
props: {
className: 'comment__text input__textarea comment__text--input',
name: 'comment[text]',
placeholder: 'Share your extensive insights...',
onkeydown: Misuzu.Comments.inputCommentHandler,
},
},
{
props: { className: 'comment__actions' },
children: {
tag: 'button',
props: {
className: 'input__button comment__action comment__action--button comment__action--post',
},
children: 'Reply',
},
},
],
},
],
},
],
},
],
},
],
});
timeago.render(commentTime);
return commentElem;
};

View file

@ -1,17 +0,0 @@
Misuzu.CSRF = {};
Misuzu.CSRF.tokenValue = undefined;
Misuzu.CSRF.tokenElement = undefined;
Misuzu.CSRF.init = function() {
Misuzu.CSRF.tokenElement = document.querySelector('[name="csrf-token"]');
Misuzu.CSRF.tokenValue = Misuzu.CSRF.tokenElement.getAttribute('value');
};
Misuzu.CSRF.getToken = function() { return Misuzu.CSRF.tokenValue || ''; };
Misuzu.CSRF.setToken = function(token) {
if(!token)
return;
Misuzu.CSRF.tokenElement.setAttribute('value', Misuzu.CSRF.tokenValue = token);
var elems = document.getElementsByName('csrf');
for(var i = 0; i < elems.length; ++i)
elems[i].value = token;
};

View file

@ -1,12 +0,0 @@
Misuzu.Events = {};
Misuzu.Events.getList = function() {
return [
new Misuzu.Events.Christmas2019,
];
};
Misuzu.Events.dispatch = function() {
var list = Misuzu.Events.getList();
for(var i = 0; i < list.length; ++i)
if(list[i].isActive())
list[i].dispatch();
};

View file

@ -1,33 +0,0 @@
Misuzu.Events.Christmas2019 = function() {
this.propName = propName = 'msz-christmas-' + (new Date).getFullYear().toString();
};
Misuzu.Events.Christmas2019.prototype.changeColour = function() {
var count = parseInt(localStorage.getItem(this.propName));
document.body.style.setProperty('--header-accent-colour', (count++ % 2) ? 'green' : 'red');
localStorage.setItem(this.propName, count.toString());
};
Misuzu.Events.Christmas2019.prototype.isActive = function() {
var d = new Date;
return d.getMonth() === 11 && d.getDate() > 5 && d.getDate() < 27;
};
Misuzu.Events.Christmas2019.prototype.dispatch = function() {
var headerBg = document.querySelector('.header__background'),
menuBgs = document.querySelectorAll('.header__desktop__submenu__background');
if(!localStorage.getItem(this.propName))
localStorage.setItem(this.propName, '0');
if(headerBg)
headerBg.style.transition = 'background-color .4s';
setTimeout(function() {
if(headerBg)
headerBg.style.transition = 'background-color 1s';
for(var i = 0; i < menuBgs.length; i++)
menuBgs[i].style.transition = 'background-color 1s';
}, 1000);
this.changeColour();
setInterval(this.changeColour, 10000);
};

View file

@ -1,81 +0,0 @@
Misuzu.FormUtils = {};
Misuzu.FormUtils.extractFormData = function(form, resetSource) {
var formData = new FormData;
for(var i = 0; i < form.length; ++i) {
if(form[i].type.toLowerCase() === 'checkbox' && !form[i].checked)
continue;
formData.append(form[i].name, form[i].value || '');
}
if(resetSource)
Misuzu.FormUtils.resetFormData(form);
return formData;
};
Misuzu.FormUtils.resetFormData = function(form, defaults) {
defaults = defaults || [];
for(var i = 0; i < form.length; ++i) {
var input = form[i];
switch(input.type.toLowerCase()) {
case 'checkbox':
input.checked = false;
break;
case 'hidden':
var hiddenDefault = defaults.find(function(fhd) { return fhd.Name.toLowerCase() === input.name.toLowerCase(); });
if(hiddenDefault)
input.value = hiddenDefault.Value;
break;
default:
input.value = '';
}
}
};
Misuzu.FormUtils.initDataRequestMethod = function() {
var links = document.links;
for(var i = 0; i < links.length; ++i) {
if(!links[i].href || !links[i].dataset || !links[i].dataset.mszMethod)
continue;
links[i].addEventListener('click', function(ev) {
Misuzu.FormUtils.handleDataRequestMethod(this, this.dataset.mszMethod, this.href);
ev.preventDefault();
});
}
};
Misuzu.FormUtils.handleDataRequestMethod = function(elem, method, url) {
var split = url.split('?', 2),
target = split[0],
query = split[1] || null;
if(elem.getAttribute('disabled'))
return;
elem.setAttribute('disabled', 'disabled');
var xhr = new XMLHttpRequest;
xhr.onreadystatechange = function(ev) {
if(xhr.readyState !== 4)
return;
elem.removeAttribute('disabled');
if(xhr.status === 301 || xhr.status === 302 || xhr.status === 307 || xhr.status === 308) {
location.assign(xhr.getResponseHeader('X-Misuzu-Location'));
return;
}
if(xhr.status >= 400 && xhr.status <= 599) {
alert(xhr.responseText);
return;
}
};
xhr.open(method, target);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('X-Misuzu-CSRF', Misuzu.CSRF.getToken());
xhr.setRequestHeader('X-Misuzu-XHR', '1');
xhr.send(query);
};

View file

@ -1 +0,0 @@
Misuzu.Forum = {};

View file

@ -1,178 +0,0 @@
Misuzu.Forum.Editor = {};
Misuzu.Forum.Editor.allowWindowClose = false;
Misuzu.Forum.Editor.init = function() {
var postingForm = document.querySelector('.js-forum-posting');
if(!postingForm)
return;
var postingButtons = postingForm.querySelector('.js-forum-posting-buttons'),
postingText = postingForm.querySelector('.js-forum-posting-text'),
postingParser = postingForm.querySelector('.js-forum-posting-parser'),
postingPreview = postingForm.querySelector('.js-forum-posting-preview'),
postingMode = postingForm.querySelector('.js-forum-posting-mode'),
previewButton = document.createElement('button'),
bbcodeButtons = document.querySelector('.forum__post__actions--bbcode'),
markdownButtons = document.querySelector('.forum__post__actions--markdown'),
markupButtons = document.querySelectorAll('.forum__post__action--tag');
// hack: don't prompt user when hitting submit, really need to make this not stupid.
postingButtons.firstElementChild.addEventListener('click', function() {
Misuzu.Forum.Editor.allowWindowClose = true;
});
window.addEventListener('beforeunload', function(ev) {
if(!Misuzu.Forum.Editor.allowWindowClose && postingText.value.length > 0) {
ev.preventDefault();
ev.returnValue = '';
}
});
for(var i = 0; i < markupButtons.length; ++i)
(function(currentBtn) {
currentBtn.addEventListener('click', function(ev) {
postingText.insertTags(currentBtn.dataset.tagOpen, currentBtn.dataset.tagClose);
});
})(markupButtons[i]);
Misuzu.Forum.Editor.switchButtons(parseInt(postingParser.value));
var lastPostText = '',
lastPostParser = null;
postingParser.addEventListener('change', function() {
var postParser = parseInt(postingParser.value);
Misuzu.Forum.Editor.switchButtons(postParser);
if(postingPreview.hasAttribute('hidden'))
return;
// dunno if this would even be possible, but ech
if(postParser === lastPostParser)
return;
postingParser.setAttribute('disabled', 'disabled');
previewButton.setAttribute('disabled', 'disabled');
previewButton.classList.add('input__button--busy');
Misuzu.Forum.Editor.renderPreview(postParser, lastPostText, function(success, text) {
if(!success) {
Misuzu.showMessageBox(text);
return;
}
if(postParser === Misuzu.Parser.markdown)
postingPreview.classList.add('markdown');
else
postingPreview.classList.remove('markdown');
lastPostParser = postParser;
postingPreview.innerHTML = text;
previewButton.removeAttribute('disabled');
postingParser.removeAttribute('disabled');
previewButton.classList.remove('input__button--busy');
});
});
previewButton.className = 'input__button';
previewButton.textContent = 'Preview';
previewButton.type = 'button';
previewButton.value = 'preview';
previewButton.addEventListener('click', function() {
if(previewButton.value === 'back') {
postingPreview.setAttribute('hidden', 'hidden');
postingText.removeAttribute('hidden');
previewButton.value = 'preview';
previewButton.textContent = 'Preview';
postingMode.textContent = postingMode.dataset.original;
postingMode.dataset.original = null;
} else {
var postText = postingText.value,
postParser = parseInt(postingParser.value);
if(lastPostText === postText && lastPostParser === postParser) {
postingPreview.removeAttribute('hidden');
postingText.setAttribute('hidden', 'hidden');
previewButton.value = 'back';
previewButton.textContent = 'Back';
postingMode.dataset.original = postingMode.textContent;
postingMode.textContent = 'Previewing';
return;
}
postingParser.setAttribute('disabled', 'disabled');
previewButton.setAttribute('disabled', 'disabled');
previewButton.classList.add('input__button--busy');
Misuzu.Forum.Editor.renderPreview(postParser, postText, function(success, text) {
if(!success) {
Misuzu.showMessageBox(text);
return;
}
if(postParser === Misuzu.Parser.markdown)
postingPreview.classList.add('markdown');
else
postingPreview.classList.remove('markdown');
lastPostText = postText;
lastPostParser = postParser;
postingPreview.innerHTML = text;
postingPreview.removeAttribute('hidden');
postingText.setAttribute('hidden', 'hidden');
previewButton.value = 'back';
previewButton.textContent = 'Back';
previewButton.removeAttribute('disabled');
postingParser.removeAttribute('disabled');
previewButton.classList.remove('input__button--busy');
postingMode.dataset.original = postingMode.textContent;
postingMode.textContent = 'Previewing';
});
}
});
postingButtons.insertBefore(previewButton, postingButtons.firstChild);
};
Misuzu.Forum.Editor.switchButtons = function(parser) {
var bbcodeButtons = document.querySelector('.forum__post__actions--bbcode'),
markdownButtons = document.querySelector('.forum__post__actions--markdown');
switch(parser) {
default:
case Misuzu.Parser.plain:
bbcodeButtons.hidden = markdownButtons.hidden = true;
break;
case Misuzu.Parser.bbcode:
bbcodeButtons.hidden = false;
markdownButtons.hidden = true;
break;
case Misuzu.Parser.markdown:
bbcodeButtons.hidden = true;
markdownButtons.hidden = false;
break;
}
};
Misuzu.Forum.Editor.renderPreview = function(parser, text, callback) {
if(!callback)
return;
parser = parseInt(parser);
text = text || '';
var xhr = new XMLHttpRequest,
formData = new FormData;
formData.append('post[mode]', 'preview');
formData.append('post[text]', text);
formData.append('post[parser]', parser.toString());
xhr.addEventListener('readystatechange', function() {
if(xhr.readyState !== XMLHttpRequest.DONE)
return;
if(xhr.status === 200)
callback(true, xhr.response);
else
callback(false, 'Failed to render preview.');
});
xhr.open('POST', Misuzu.Urls.format('forum-topic-new'));
xhr.withCredentials = true;
xhr.send(formData);
};

View file

@ -1,15 +0,0 @@
Misuzu.Perms = function(perms) {
this.perms = perms || {};
};
Misuzu.Perms.prototype.perms = undefined;
Misuzu.Perms.check = function(section, value) {
return function() { return this.perms[section] && (this.perms[section] & value) > 0; };
};
// Comment permissions
Misuzu.Perms.prototype.canCreateComment = Misuzu.Perms.check('comments', 0x01);
Misuzu.Perms.prototype.canDeleteOwnComment = Misuzu.Perms.check('comments', 0x08 | 0x10);
Misuzu.Perms.prototype.canDeleteAnyComment = Misuzu.Perms.check('comments', 0x10);
Misuzu.Perms.prototype.canLockCommentSection = Misuzu.Perms.check('comments', 0x20);
Misuzu.Perms.prototype.canPinComment = Misuzu.Perms.check('comments', 0x40);
Misuzu.Perms.prototype.canVoteOnComment = Misuzu.Perms.check('comments', 0x80);

View file

@ -1,66 +0,0 @@
Misuzu.Urls = {};
Misuzu.Urls.registry = [];
Misuzu.Urls.loadFromDocument = function() {
var elem = document.getElementById('js-urls-list');
if(!elem)
return;
Misuzu.Urls.registry = JSON.parse(elem.textContent);
};
Misuzu.Urls.handleVariable = function(value, vars) {
if(value[0] === '<' && value.slice(-1) === '>')
return (vars.find(function(x) { return x.name == value.slice(1, -1); }) || {}).value || '';
if(value[0] === '[' && value.slice(-1) === ']')
return ''; // not sure if there's a proper substitute for this, should probably resolve these in url_list
if(value[0] === '{' && value.slice(-1) === '}')
return Misuzu.CSRF.getToken();
// Allow file extensions
var split = value.split('.'),
extension = split[split.length - 1],
fileName = split.slice(0, -1).join('.');
if(value !== fileName) {
var fallback = Misuzu.Urls.handleVariable(fileName, vars);
if(fallback !== fileName)
return fallback + '.' + extension;
}
return value;
};
Misuzu.Urls.v = function(name, value) {
if(typeof value === 'undefined' || value === null)
value = '';
return { name: name.toString(), value: value.toString() };
};
Misuzu.Urls.format = function(name, vars) {
vars = vars || [];
var entry = Misuzu.Urls.registry.find(function(x) { return x.name == name; });
if(!entry || !entry.path)
return '';
var split = entry.path.split('/');
for(var i = 0; i < split.length; ++i)
split[i] = Misuzu.Urls.handleVariable(split[i], vars);
var url = split.join('/');
if(entry.query) {
url += '?';
for(var i = 0; i < entry.query.length; ++i) {
var query = entry.query[i],
value = Misuzu.Urls.handleVariable(query.value, vars);
if(!value || (query.name === 'page' && parseInt(value) < 2))
continue;
url += query.name + '=' + value.toString() + '&';
}
url = url.replace(/^[\?\&]+|[\?\&]+$/g, '');
}
if(entry.fragment)
url += ('#' + Misuzu.Urls.handleVariable(entry.fragment, vars)).replace(/[\#]+$/g, '');
return url;
};

View file

@ -1,19 +0,0 @@
Misuzu.User = function(userInfo) {
this.id = parseInt(userInfo.user_id || 0);
this.name = (userInfo.username || '').toString();
this.colour = new Misuzu.Colour(userInfo.user_colour || Misuzu.Colour.FLAG_INHERIT);
this.perms = new Misuzu.Perms(userInfo.perms || {});
};
Misuzu.User.localUser = undefined;
Misuzu.User.refreshLocalUser = function() {
var userInfo = document.getElementById('js-user-info');
if(!userInfo)
Misuzu.User.localUser = undefined;
else
Misuzu.User.localUser = new Misuzu.User(JSON.parse(userInfo.textContent));
};
Misuzu.User.isLoggedIn = function() { return Misuzu.User.localUser !== undefined; };
Misuzu.User.prototype.getId = function() { return this.id || 0; };
Misuzu.User.prototype.getUsername = function() { return this.name || ''; };
Misuzu.User.prototype.getColour = function() { return this.colour || null; };

31
assets/misuzu.css/bb.css Normal file
View file

@ -0,0 +1,31 @@
.bb-h1, .bb-h2,
.bb-h3, .bb-h4,
.bb-h5, .bb-h6 {
font-weight: 700;
line-height: 1.5em;
display: inline-block;
width: 100%;
margin-bottom: .25em;
}
.bb-h1 {
font-size: 2em;
border-bottom: 1px solid var(--accent-colour);
}
.bb-h2 {
font-size: 1.5em;
border-bottom: 1px solid var(--accent-colour);
}
.bb-h3 {
font-size: 1.25em;
}
.bb-h4 {
font-size: 1em;
}
.bb-h5 {
font-size: 0.875em;
}
.bb-h6 {
font-size: 0.85em;
color: var(--accent-colour);
}

View file

@ -1,7 +1,6 @@
.container {
background-color: var(--container-colour);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
text-shadow: 0 1px 4px #000;
overflow: hidden;
word-wrap: break-word;
}

View file

@ -0,0 +1,104 @@
.eeprom-widget {
background-color: var(--container-colour);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
text-shadow: 0 1px 4px #000;
display: flex;
min-height: 50px;
}
.eeprom-widget-form {
display: flex;
text-align: center;
justify-content: center;
align-items: center;
flex: 0 0 auto;
min-width: 154px; /* same width as sidebar */
background-color: #aaa1;
transition: background-color .2s;
}
.eeprom-widget-form-input {
display: none;
visibility: hidden;
}
.eeprom-widget-form-text {
font-size: 1.4em;
line-height: 1.5em;
}
.eeprom-widget-form:focus,
.eeprom-widget-form:hover {
background-color: #fff1;
}
.eeprom-widget-form:active {
background-color: #ccc1;
}
.eeprom-widget-history {
overflow-y: auto;
scrollbar-width: thin;
}
.eeprom-widget-history-items {
display: flex;
padding: 0 3px;
}
.eeprom-widget-file {
margin: 4px 1px;
padding-top: 2px; /* adjust for the progress bar */
border: 1px solid var(--accent-colour);
border-radius: 2px;
overflow: hidden;
width: 200px;
flex: 0 0 auto;
}
.eeprom-widget-file-fail {
--accent-color: #c00;
}
.eeprom-widget-file-info {
padding: 0 2px;
}
.eeprom-widget-file-name {
color: #fff;
text-decoration: none;
}
.eeprom-widget-file-name-value {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.eeprom-widget-file-name:hover,
.eeprom-widget-file-name:focus {
text-decoration: underline;
}
.eeprom-widget-file-progress {
font-size: .9em;
line-height: 1.4em;
text-align: right;
padding: 0 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.eeprom-widget-file-progress a {
color: var(--accent-colour);
text-decoration: none;
}
.eeprom-widget-file-progress a:hover,
.eeprom-widget-file-progress a:focus {
text-decoration: underline;
}
.eeprom-widget-file-bar {
width: 100%;
height: 2px;
display: flex;
justify-content: flex-start;
align-items: flex-end;
}
.eeprom-widget-file-bar-fill {
width: 0%;
height: 2px;
background-color: var(--accent-colour);
transition: width .1s, height .1s;
}
.eeprom-widget-file-done .eeprom-widget-file-bar-fill {
height: 0;
}

374
assets/misuzu.css/embed.css Normal file
View file

@ -0,0 +1,374 @@
.embed {
display: inline-block;
overflow: hidden;
}
.embed iframe {
width: 100%;
height: 100%;
display: block;
}
.embedph {
display: inline-block;
overflow: hidden;
cursor: pointer;
color: var(--text-colour);
text-decoration: none;
}
.embedph:hover .embedph-bg img,
.embedph:active .embedph-bg img,
.embedph:focus .embedph-bg img,
.embedph:focus-within .embedph-bg img {
transform: scale(1.1);
filter: blur(10px) brightness(80%);
}
.embedph:hover .embedph-info,
.embedph:active .embedph-info,
.embedph:focus .embedph-info,
.embedph:focus-within .embedph-info {
opacity: 0;
}
.embedph:hover .embedph-play,
.embedph:active .embedph-play,
.embedph:focus .embedph-play,
.embedph:focus-within .embedph-play {
opacity: 1;
}
.embedph-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.embedph-bg img {
object-fit: cover;
width: 100%;
height: 100%;
display: inline-block;
transition: transform .2s, filter .2s;
box-sizing: border-box !important;
max-width: initial !important;
max-height: initial !important;
}
.embedph-fg {
width: 100%;
height: 100%;
}
.embedph-info {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: flex-end;
transition: opacity .2s;
}
.embedph-info-wrap {
margin: 5px;
background-color: var(--background-colour-translucent-8);
border-radius: 5px;
display: flex;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.embedph-info-bar {
width: 5px;
margin: 5px;
border-radius: 5px;
flex: 0 0 auto;
background-color: var(--embedph-colour, var(--accent-colour));
}
.embedph-info-body {
margin: 10px;
margin-left: 5px;
}
.embedph-info-title {
font-size: 2em !important;
font-weight: 400 !important;
line-height: 1.2em !important;
margin-bottom: 5px;
word-break: break-word;
margin: 0 !important;
padding: 0 !important;
border-width: 0 !important;
}
.embedph-info-desc {
line-height: 1.4em;
margin: .5em 0;
word-break: break-word;
}
.embedph-info-site {
font-size: .9em;
line-height: 1.2em;
}
@media (max-width: 640px) {
.embedph-info-title {
font-size: 1.5em;
line-height: 1.2em;
}
.embedph-info-desc {
display: none;
}
}
.embedph-play {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity .2s;
}
.embedph-play-internal {
margin-top: 40px;
margin-bottom: 20px;
}
.embedph-play-external {
padding: 5px 10px;
font-size: 1.2em;
line-height: 1.5em;
text-decoration: none !important;
color: var(--text-colour) !important;
background-color: var(--background-colour-translucent-6);
border-radius: 5px;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
transition: background-color .2s, transform .2s;
}
.embedph-play-external:hover,
.embedph-play-external:focus {
background-color: var(--background-colour-translucent-8);
transform: scale(1.2);
}
.embed-youtube,
.embedph-youtube {
aspect-ratio: 16 / 9;
width: 100%;
height: 100%;
max-width: 560px;
max-height: 315px;
}
.embed-nicovideo,
.embedph-nicovideo {
aspect-ratio: 16 / 9;
width: 100%;
height: 100%;
max-width: 640px;
max-height: 360px;
}
.embedvf {
display: inline-block;
overflow: hidden;
}
.embedvf:hover .embedvf-controls,
.embedvf:focus .embedvf-controls,
.embedvf:active .embedvf-controls,
.embedvf:focus-within .embedvf-controls {
opacity: 1;
transform: scale(1);
}
.embedvf-player {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.embedvf-overlay {
width: 100%;
height: 100%;
pointer-events: none;
}
.embedvf-controls {
pointer-events: initial;
position: absolute;
bottom: 5px;
left: 5px;
right: 5px;
padding: 5px;
background-color: var(--background-colour-translucent-7);
border-radius: 5px;
opacity: 0;
transform: scale(.95);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
transition: opacity .2s, transform .2s;
}
.aembed {
display: inline-block;
overflow: hidden;
}
.aembedph {
display: inline-block;
overflow: hidden;
cursor: pointer;
color: var(--text-colour);
text-decoration: none;
max-width: 500px;
min-width: 300px;
height: 70px;
border-radius: 5px;
margin: 5px;
}
.aembedph:hover .aembedph-play,
.aembedph:active .aembedph-play,
.aembedph:focus .aembedph-play,
.aembedph:focus-within .aembedph-play {
opacity: 1;
}
.aembedph-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.aembedph-bg-none {
background: var(--background-pattern);
background-color: var(--aembedph-colour, var(--accent-colour));
background-blend-mode: multiply;
}
.aembedph-bg img {
object-fit: cover;
width: 100%;
height: 100%;
display: inline-block;
transform: scale(1.1);
filter: blur(10px) brightness(80%);
box-sizing: border-box !important;
max-width: initial !important;
max-height: initial !important;
}
.aembedph-fg {
width: 100%;
height: 100%;
}
.aembedph-info {
display: flex;
background-color: var(--background-colour-translucent-5);
align-items: center;
width: 100%;
height: 100%;
padding: 5px;
}
.aembedph-info-cover {
flex: 0 0 auto;
overflow: hidden;
border-radius: 5px;
}
.aembedph-info-cover-none {
background-color: var(--aembedph-colour, var(--accent-colour));
width: 5px;
height: 100%;
}
.aembedph-info-cover img {
max-width: 60px !important;
max-height: 60px !important;
display: inline-block;
vertical-align: middle;
box-sizing: border-box !important;
}
.aembedph-info-cover-none img {
display: none;
}
.aembedph-info-body {
padding: 0 5px;
}
.aembedph-info-title {
font-size: 1.4em !important;
font-weight: 400 !important;
line-height: 1.2em !important;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 430px;
margin: 0 !important;
padding: 0 !important;
border-width: 0 !important;
}
.aembedph-info-title-artist {
max-width: 200px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 700;
}
.aembedph-info-album {
line-height: 1.4em;
word-break: break-word;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 430px;
}
.aembedph-info-site {
font-size: .9em;
line-height: 1.2em;
}
.aembedph-play {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity .2s;
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
}
.aembedph-play-internal {
width: 70px;
height: 70px;
text-align: center;
flex: 0 0 auto;
display: flex;
justify-content: center;
align-items: center;
}
.aembedph-play-external {
flex: 1 1 auto;
display: flex;
justify-content: flex-end;
align-items: center;
padding: 5px;
}
.aembedph-play-external-link {
padding: 2px 5px;
line-height: 1.5em;
text-decoration: none !important;
color: var(--text-colour) !important;
background-color: var(--background-colour-translucent-6);
border-radius: 5px;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
transition: background-color .2s;
}
.aembedph-play-external-link:hover,
.aembedph-play-external-link:focus {
background-color: var(--background-colour-translucent-8);
}
.aembedph-play-external-link:active {
background-color: var(--background-colour-translucent-5);
}

View file

@ -139,7 +139,7 @@
.forum__category__activity {
text-align: right;
min-width: 270px;
line-height: 1.5em;
line-height: 1.4em;
}
.forum__category__activity__none,
.forum__category__activity__details {
@ -171,6 +171,7 @@
color: var(--user-colour);
text-decoration: none;
pointer-events: initial;
display: block;
}
.forum__category__username:hover,
.forum__category__username:focus {
@ -229,4 +230,7 @@
.forum__category__avatar {
display: none;
}
}
.forum__category__username {
display: none;
}
}

View file

@ -46,15 +46,11 @@
}
.forum__post__text {
margin: 2px;
line-height: 1.2em;
padding: 2px;
line-height: 1.4em;
flex: 1 1 auto;
overflow: auto;
}
.forum__post__text--edit {
/* figure out why this is needed */
max-width: calc(100% - 4px);
min-width: calc(100% - 4px);
.forum__post__text--edit {
margin: 2px 2px 0;
min-height: 400px;
height: 100%;
@ -66,6 +62,12 @@
font-family: inherit;
}
.forum__post__text img {
vertical-align: middle;
max-width: 100%;
max-height: 900px
}
.forum__post__info__content {
width: 150px;
text-align: center;
@ -152,6 +154,9 @@
}
.forum__post__action {
background-color: transparent;
border: 0;
display: block;
padding: 5px 10px;
margin: 1px;
color: inherit;
@ -173,6 +178,8 @@
}
.forum__post__signature img {
vertical-align: middle;
max-width: 100%;
max-height: 150px;
}
.forum__post__badge {

View file

@ -146,9 +146,14 @@
}
.header__desktop__user__button__count {
position: absolute;
bottom: 1px;
right: 1px;
font-size: 10px;
top: -5px;
right: -3px;
z-index: 1;
font-size: .5em;
line-height: 1.4em;
text-align: right;
padding: 2px 2px 0;
border-radius: 4px;
background-color: var(--header-accent-colour);
opacity: .9;
border-radius: 4px;
@ -224,7 +229,6 @@
background-blend-mode: multiply;
transition: max-height .2s;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
text-shadow: 0 1px 4px #000;
max-height: 0;
overflow: hidden;
}

View file

@ -0,0 +1,92 @@
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em;
font-size: 1.2em;
font-family: var(--font-monospace);
}
code.hljs {
padding: 2px 5px;
}
.hljs {
color: #eee;
background: #121212;
}
.hljs-strong,
.hljs-emphasis,
.hljs-section {
font-weight: 700;
}
.hljs-bullet,
.hljs-quote,
.hljs-number,
.hljs-regexp,
.hljs-literal {
color: #b2b376;
}
.hljs-code {
background-color: #242424;
}
.hljs-comment,
.hljs-meta,
.hljs-emphasis,
.hljs-stronge,
.hljs-type,
.hljs-attribute,
.hljs-params {
font-style: italic;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-section,
.hljs-symbol,
.hljs-name {
color: #9475b2;
}
.hljs-built_in,
.hljs-subst,
.hljs-tag,
.hljs-title,
.hljs-selector-attr {
color: #c8b9d7;
}
.hljs-variable,
.hljs-class .hljs-title,
.hljs-selector-class,
.hljs-selector-id,
.hljs-selector-pseudo {
color: #b37fae;
}
.hljs-string {
color: #76b38a;
}
.hljs-type,
.hljs-template-tag,
.hljs-template-variable,
.hljs-link {
color: #b39a76;
}
.hljs-comment,
.hljs-meta {
color: #70647b;
}
.hljs-addition {
background: #0e4d0e;
}
.hljs-deletion {
background: #4d0e0e;
}

View file

@ -0,0 +1,53 @@
.impersonate {
--start-colour: var(--accent-colour);
--end-colour: var(--background-colour);
background-image: repeating-linear-gradient(-45deg, var(--start-colour), var(--start-colour) 10px, var(--end-colour) 10px, var(--end-colour) 20px);
height: 30px;
}
.impersonate-content {
max-width: var(--site-max-width);
margin: 0 auto;
display: flex;
justify-content: space-between;
height: 100%;
}
.impersonate-user {
padding: 4px 10px;
background-color: #222d;
}
.impersonate-user-link {
color: var(--user-colour);
text-decoration: none;
}
.impersonate-user-link:hover,
.impersonate-user-link:focus {
text-decoration: underline;
}
.impersonate-user-avatar {
display: inline-block;
}
.impersonate-options {
display: flex;
}
.impersonate-options-link {
width: 30px;
height: 30px;
line-height: 29px;
text-align: center;
font-size: 1.5em;
background-color: #222d;
display: block;
color: var(--text-colour);
text-decoration: none;
transition: background-color .1s;
}
.impersonate-options-link:focus,
.impersonate-options-link:hover {
background-color: #555d;
}
.impersonate-options-link:active {
background-color: #333d;
}

203
assets/misuzu.css/main.css Normal file
View file

@ -0,0 +1,203 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
position: relative;
}
html,
body {
width: 100%;
height: 100%;
}
[hidden],
.hidden {
display: none !important;
visibility: hidden !important;
}
:root {
--font-size: 12px;
--line-height: 20px;
--font-regular: Verdana, Geneva, 'Dejavu Sans', Arial, Helvetica, sans-serif;
--font-monospace: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
--site-max-width: 1200px;
--site-mobile-width: 800px;
--site-logo: url('/images/logos/imouto-default.png');
--header-height-desktop: 70px;
--header-height-mobile: 50px;
--background-image: initial;
--background-colour: #111;
--background-colour-translucent-1: rgba(17, 17, 17, 0.1);
--background-colour-translucent-2: rgba(17, 17, 17, 0.2);
--background-colour-translucent-3: rgba(17, 17, 17, 0.3);
--background-colour-translucent-4: rgba(17, 17, 17, 0.4);
--background-colour-translucent-5: rgba(17, 17, 17, 0.5);
--background-colour-translucent-6: rgba(17, 17, 17, 0.6);
--background-colour-translucent-7: rgba(17, 17, 17, 0.7);
--background-colour-translucent-8: rgba(17, 17, 17, 0.8);
--background-colour-translucent-9: rgba(17, 17, 17, 0.9);
--background-pattern: url('/images/clouds.png') fixed;
--container-colour: #161616;
--text-colour: #fff;
--text-colour-inverted: #000;
--user-colour: inherit;
--user-header: url('/images/pixel.png');
--accent-colour: #8559a5;
--header-accent-colour: var(--accent-colour);
}
html {
scrollbar-color: var(--accent-colour) var(--background-colour);
accent-color: var(--accent-colour);
color-scheme: dark;
}
.main {
display: flex;
flex-direction: column;
background-image: var(--background-image);
background-color: var(--background-colour);
font-size: var(--font-size);
line-height: var(--line-height);
font-family: var(--font-regular);
color: var(--text-colour);
background-attachment: fixed;
background-position: center center;
}
.main__wrapper {
max-width: var(--site-max-width);
width: 100%;
margin: 0 auto;
flex: 1 0 auto;
}
.main--bg-blend {
background-color: var(--accent-colour);
background-blend-mode: multiply;
}
.main--bg-slide { animation: background-slide infinite linear 2s; }
.main--bg-cover { background-size: cover; }
.main--bg-contain { background-size: contain; }
.main--bg-stretch { background-size: 100% 100%; }
.main--bg-tile { background-size: auto; }
.link {
color: var(--accent-colour);
text-decoration: none;
}
.link:hover, .link:focus { text-decoration: underline; }
@comment "convert all of the below into a proper inclusion structure";
@include animations.css;
@include avatar.css;
@include bb.css;
@include confirm.css;
@include container.css;
@include eeprom.css;
@include embed.css;
@include emoticon.css;
@include flags.css;
@include footer.css;
@include header.css;
@include impersonate.css;
@include landing.css;
@include main.css;
@include markdown.css;
@include messagebox.css;
@include navigation.css;
@include pagination.css;
@include permissions.css;
@include warning.css;
@include hljs.css;
@include _input/button.css;
@include _input/checkbox.css;
@include _input/colour.css;
@include _input/select.css;
@include _input/text.css;
@include _input/textarea.css;
@include _input/upload.css;
@include auth/buttons.css;
@include auth/container.css;
@include auth/label.css;
@include auth/login.css;
@include auth/logout.css;
@include auth/register.css;
@include auth/warning.css;
@include changelog/_changelog.css;
@include changelog/change.css;
@include changelog/container.css;
@include changelog/entry.css;
@include changelog/listing.css;
@include changelog/log.css;
@include changelog/pagination.css;
@include comments/comment.css;
@include comments/comments.css;
@include forum/actions.css;
@include forum/categories.css;
@include forum/confirm.css;
@include forum/header.css;
@include forum/leaderboard.css;
@include forum/poll.css;
@include forum/post.css;
@include forum/priority.css;
@include forum/status.css;
@include forum/topics.css;
@include home/landingv2-footer.css;
@include home/landingv2-header.css;
@include home/landingv2.css;
@include manage/_manage.css;
@include messages/messages.css;
@include news/container.css;
@include news/feeds.css;
@include news/list.css;
@include news/post.css;
@include news/preview.css;
@include news/sidebar.css;
@include profile/about.css;
@include profile/accounts.css;
@include profile/birthdate.css;
@include profile/forum-activity.css;
@include profile/guidelines.css;
@include profile/header.css;
@include profile/profile.css;
@include profile/signature.css;
@include profile/warnings.css;
@include search/anchor.css;
@include search/categories.css;
@include search/container.css;
@include search/header.css;
@include search/input.css;
@include search/none.css;
@include settings/account-logs.css;
@include settings/account.css;
@include settings/data.css;
@include settings/login-attempts.css;
@include settings/role.css;
@include settings/sessions.css;
@include settings/settings.css;
@include settings/two-factor.css;
@include user/usercard.css;
@include user/userlist.css;

View file

@ -0,0 +1,47 @@
.manage {
display: flex;
}
.manage__sidebar {
flex: 0 0 auto;
width: 280px;
}
.manage__content {
flex: 1 1 auto;
}
.manage__description {
font-size: .9em;
margin: 1px 2px;
border-bottom: 1px solid var(--accent-colour);
padding: 2px 5px;
}
@media (max-width: 800px) {
.manage {
flex-direction: column;
}
.manage__sidebar {
width: 100%;
}
}
@include manage/ban.css;
@include manage/bans.css;
@include manage/blacklist.css;
@include manage/changelog-actions-tags.css;
@include manage/emote.css;
@include manage/emotes.css;
@include manage/navigation.css;
@include manage/note.css;
@include manage/notes.css;
@include manage/role-item.css;
@include manage/roles.css;
@include manage/settings.css;
@include manage/statistic.css;
@include manage/statistics.css;
@include manage/tag.css;
@include manage/tags.css;
@include manage/user-item.css;
@include manage/user.css;
@include manage/users.css;
@include manage/warning.css;
@include manage/warnings.css;

View file

@ -0,0 +1,73 @@
.manage__ban__field {
margin: 2px;
margin-bottom: 8px;
}
.manage__ban__title {
font-size: 1.4em;
line-height: 1.5em;
padding: 0 4px;
}
.manage__ban__desc {
font-size: .9em;
line-height: 1.5em;
font-style: italic;
border-bottom: 1px solid var(--accent-colour);
padding: 2px 4px;
margin-bottom: 1px;
}
.manage__ban__duration {
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
gap: 5px;
}
.manage__ban__duration__value__custom--hidden {
display: none;
visibility: hidden;
}
.manage__ban__severity {
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
gap: 5px;
}
.manage__ban__severity__slider {
max-width: 200px;
width: 100%;
}
.manage__ban__severity__slider input {
width: 100%;
margin-top: 2px;
}
.manage__ban__severity__display {
max-width: 80px;
width: 100%;
}
.manage__ban__severity__display input {
width: 100%;
margin-bottom: 2px;
}
.manage__ban__reason {
padding: 2px;
width: 100%;
}
.manage__ban__reason textarea {
min-width: 100%;
max-width: 100%;
width: 100%;
min-height: 100px;
}
.manage__ban__actions {
display: flex;
justify-content: center;
padding: 10px;
padding-top: 0;
}

View file

@ -0,0 +1,122 @@
.manage__bans__pagination {
margin: 2px;
}
.manage__bans__actions {
display: flex;
gap: 2px;
margin: 2px;
}
.manage__bans__item {
padding: 0 2px;
margin: 2px;
border-top: 1px solid var(--accent-colour);
}
.manage__bans__item:not(:last-child) {
border-bottom: 1px solid var(--accent-colour);
}
.manage__bans__item__header {
display: flex;
overflow: hidden;
align-items: center;
}
.manage__bans__item__attributes {
flex-grow: 1;
flex-shrink: 1;
display: flex;
gap: 12px;
margin: 0 4px;
flex-wrap: wrap;
}
.manage__bans__item__attribute {
display: flex;
gap: 4px;
align-items: center;
}
.manage__bans__item__created__icon,
.manage__bans__item__expires__icon,
.manage__bans__item__permanent__icon {
font-size: 16px;
}
.manage__bans__item__expires__status span {
padding: 2px 4px;
border-radius: 2px;
}
.manage__bans__item__expires__status--active span {
background: rgba(255, 100, 100, 0.2);
font-weight: 700;
}
.manage__bans__item__expires__status--expired span {
background: rgba(100, 255, 100, 0.2);
}
.manage__bans__item__permanent {
background: rgba(255, 200, 100, 0.2);
border-radius: 2px;
padding: 0 4px;
}
.manage__bans__item__permanent__time {
font-weight: 700;
}
.manage__bans__item__actions {
display: flex;
flex-grow: 0;
flex-shrink: 0;
gap: 1px;
padding: 1px;
margin: 1px;
}
.manage__bans__item__action {
width: 36px;
height: 36px;
}
.manage__bans__item__author a,
.manage__bans__item__user a {
color: inherit;
text-decoration: none;
}
.manage__bans__item__author__name a,
.manage__bans__item__user__name a {
font-weight: bold;
display: inline-block;
padding-top: 2px;
border-bottom: 2px solid var(--user-colour, #fff);
}
.manage__bans__item__user__filter a {
padding: 2px 4px;
border-radius: 2px;
background: rgba(255, 255, 255, 0.2);
transition: background .2s;
}
.manage__bans__item__user__filter a:hover,
.manage__bans__item__user__filter a:focus {
background: rgba(255, 255, 255, 0.4);
}
.manage__bans__item__user__filter a:active {
background: rgba(255, 255, 255, 0.1);
}
.manage__bans__item__reason {
margin: 1px 4px;
padding: 2px 4px;
border-top: 1px solid var(--accent-colour);
}
.manage__bans__item__reason__title {
font-size: .9em;
line-height: 1.5em;
font-style: italic;
}
.manage__bans__item__reason__body {
padding-left: 4px;
border-left: 2px solid var(--accent-colour);
}
.manage__bans__item__noreason {
font-size: .9em;
font-style: italic;
}

View file

@ -0,0 +1,88 @@
.manage__note {
margin: 2px;
}
.manage__note--view .manage__note--editing,
.manage__note--edit .manage__note--viewing {
display: none !important;
visibility: hidden !important;
}
.manage__note__header {
display: flex;
overflow: hidden;
align-items: center;
}
.manage__note__title {
flex-grow: 1;
flex-shrink: 1;
font-size: 1.4em;
line-height: 1.3em;
}
.manage__note__title__text {
padding: 2px 5px;
}
.manage__note__title input {
width: 100%;
}
.manage__note__actions {
display: flex;
flex-grow: 0;
flex-shrink: 0;
gap: 1px;
padding: 1px;
margin: 1px;
}
.manage__note__action {
width: 36px;
height: 36px;
}
.manage__note__attributes {
display: flex;
gap: 12px;
margin: 0 4px;
}
.manage__note__attribute {
display: flex;
gap: 4px;
align-items: center;
}
.manage__note__created__icon {
font-size: 16px;
}
.manage__note__author a,
.manage__note__user a {
color: inherit;
text-decoration: none;
}
.manage__note__author__name a,
.manage__note__user__name a {
font-weight: bold;
display: inline-block;
padding-top: 2px;
border-bottom: 2px solid var(--user-colour, #fff);
}
.manage__note__body {
margin: 2px;
}
.manage__note__nobody {
text-align: center;
font-size: .9em;
font-style: italic;
}
.manage__note__editor {
width: 100%;
}
.manage__note__editor textarea {
width: 100%;
min-width: 100%;
max-width: 100%;
min-height: 300px;
}

View file

@ -0,0 +1,122 @@
.manage__notes__pagination {
margin: 2px;
}
.manage__notes__actions {
display: flex;
gap: 2px;
margin: 2px;
}
.manage__notes__item {
padding: 2px;
margin: 2px;
}
.manage__notes__item:not(:last-child) {
border-bottom: 1px solid var(--accent-colour);
}
.manage__notes__item__header {
display: flex;
overflow: hidden;
align-items: center;
}
.manage__notes__item__title {
flex-grow: 1;
flex-shrink: 1;
font-size: 1.4em;
line-height: 1.3em;
padding: 2px 5px;
}
.manage__notes__item__title a {
color: inherit;
text-decoration: none;
}
.manage__notes__item__title a:hover,
.manage__notes__item__title a:focus {
text-decoration: underline;
}
.manage__notes__item__actions {
display: flex;
flex-grow: 0;
flex-shrink: 0;
gap: 1px;
padding: 1px;
margin: 1px;
}
.manage__notes__item__action {
width: 36px;
height: 36px;
}
.manage__notes__item__attributes {
display: flex;
gap: 12px;
margin: 0 4px;
}
.manage__notes__item__attribute {
display: flex;
gap: 4px;
align-items: center;
}
.manage__notes__item__created__icon {
font-size: 16px;
}
.manage__notes__item__author a,
.manage__notes__item__user a {
color: inherit;
text-decoration: none;
}
.manage__notes__item__author__name a,
.manage__notes__item__user__name a {
font-weight: bold;
display: inline-block;
padding-top: 2px;
border-bottom: 2px solid var(--user-colour, #fff);
}
.manage__notes__item__user__filter a {
padding: 2px 4px;
border-radius: 2px;
background: rgba(255, 255, 255, 0.2);
transition: background .2s;
}
.manage__notes__item__user__filter a:hover,
.manage__notes__item__user__filter a:focus {
background: rgba(255, 255, 255, 0.4);
}
.manage__notes__item__user__filter a:active {
background: rgba(255, 255, 255, 0.1);
}
.manage__notes__item__body {
margin: 2px;
}
.manage__notes__item__nobody {
text-align: center;
font-size: .9em;
font-style: italic;
}
.manage__notes__item__continue {
text-align: center;
}
.manage__notes__item__continue a {
display: inline-block;
padding: 2px 5px;
color: inherit;
text-decoration: none;
border-radius: 5px;
background: rgba(255, 255, 255, 0.2);
background: rgba(255, 255, 255, 0.2);
transition: background .2s;
}
.manage__notes__item__continue a:hover,
.manage__notes__item__continue a:focus {
background: rgba(255, 255, 255, 0.4);
}
.manage__notes__item__continue a:active {
background: rgba(255, 255, 255, 0.1);
}

View file

@ -1,6 +1,5 @@
.manage__role-item {
display: flex;
text-shadow: 0 1px 4px #000;
box-shadow: 0 1px 4px #000A;
margin-bottom: 4px;
}
@ -38,6 +37,7 @@
width: 40px;
height: 40px;
box-shadow: 0 1px 4px #111;
text-shadow: 0 1px 4px #000;
margin: 10px;
flex: 0 0 auto;
overflow: hidden;

View file

@ -36,10 +36,13 @@
.manage-list-setting-type--string {
--type-colour: #ef8323;
}
.manage-list-setting-type--integer {
.manage-list-setting-type--int {
--type-colour: #8c90bc;
}
.manage-list-setting-type--boolean {
.manage-list-setting-type--float {
--type-colour: #cb09c8;
}
.manage-list-setting-type--bool {
--type-colour: #77b34c;
}
.manage-list-setting-type--array {
@ -48,7 +51,6 @@
.manage-list-setting-type-text {
background: var(--type-colour);
border-radius: 5px;
text-shadow: initial;
font-weight: 700;
padding: 0 5px;
font-size: .9em;

View file

@ -9,6 +9,12 @@
}
.manage__statistic__value {
text-align: right;
font-size: 1.5em;
line-height: 2em;
font-size: 1.4em;
line-height: 1.5em;
}
.manage__statistic__updated {
text-align: right;
font-size: .9em;
font-style: italic;
line-height: 1.5em;
}

View file

@ -1,9 +1,14 @@
.manage__statistics {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr 1fr;
padding: 5px;
grid-gap: 5px;
}
@media (max-width: 1100px) {
.manage__statistics {
grid-template-columns: 1fr 1fr 1fr;
}
}
@media (max-width: 900px) {
.manage__statistics {
grid-template-columns: 1fr 1fr;

View file

@ -1,6 +1,5 @@
.manage__user-item {
display: flex;
text-shadow: 0 1px 4px #000;
box-shadow: 0 1px 4px #000A;
margin-bottom: 4px;
}
@ -60,6 +59,7 @@
.manage__user-item__name {
font-size: 1.4em;
line-height: 1.4em;
max-width: 600px; /* whatever */
}
.manage__user-item__details {

View file

@ -0,0 +1,37 @@
.manage__warning__field {
margin: 2px;
margin-bottom: 8px;
}
.manage__warning__title {
font-size: 1.4em;
line-height: 1.5em;
padding: 0 4px;
}
.manage__warning__desc {
font-size: .9em;
line-height: 1.5em;
font-style: italic;
border-bottom: 1px solid var(--accent-colour);
padding: 2px 4px;
margin-bottom: 1px;
}
.manage__warning__body {
padding: 2px;
width: 100%;
}
.manage__warning__body textarea {
min-width: 100%;
max-width: 100%;
width: 100%;
min-height: 100px;
}
.manage__warning__actions {
display: flex;
justify-content: center;
padding: 10px;
padding-top: 0;
}

Some files were not shown because too many files have changed in this diff Show more