Compare commits

...

265 commits

Author SHA1 Message Date
flash 5d3e1d4960 Fixed wrong HTTP verb. 2024-03-30 15:22:11 +00:00
flash 9bb943bacf Fixed various oversights. 2024-03-30 03:19:08 +00:00
flash 107d16cf46 Updated Misuzu to new HTTP router. 2024-03-30 03:14:03 +00:00
flash 0afc5186a7 Fixed error when trying to access a topic with no posts associated. 2024-02-24 22:03:32 +00:00
flash 0300bae994 hurr 2024-02-21 00:31:25 +00:00
flash cb0c64f8ed Stinky fix for impersonation in chat auth. 2024-02-20 23:56:43 +00:00
flash 89ef9d9ad1 Fixed bans no longer working. 2024-02-15 22:55:24 +00:00
flash c02d922dc6 Fixed Forum Activity section always showing up. 2024-02-13 21:22:56 +00:00
flash 80cd6222c4 Fixed profile fields not showing up anymore. 2024-02-11 02:22:22 +00:00
flash 344a3c9160 Missed one! 2024-02-09 16:07:43 +00:00
flash df5dbdf3ad Fixed forum/topic breadcrumbs. 2024-02-08 15:20:44 +00:00
flash c0caceed7b Fixed use of wrong BanInfo constructor. 2024-02-08 15:18:57 +00:00
flash be54ce2c22 Fixed oversights on landing page. 2024-02-08 00:06:23 +00:00
flash 070dc5e782 Added lazy database object creation. 2024-02-07 00:04:45 +00:00
flash b89621cb1a Added PMs to data export. 2024-02-05 22:56:51 +00:00
flash 760cca0e5d whoops 2024-02-02 21:53:36 +00:00
flash fe77f1616c Updated to new EEPROM script. 2024-02-02 21:42:40 +00:00
flash eb81ed7a82 Added notice when recipient is banned. 2024-02-02 02:16:37 +00:00
flash 8ef11afe02 Check if recipient is actually able to receive messages. 2024-02-02 02:07:29 +00:00
flash cca016ba10 Prevent banned users from sending messages. 2024-02-02 01:59:21 +00:00
flash b80151583e Added private messages. 2024-01-30 23:47:02 +00:00
flash d8cc208a85 Use accent-color and color-scheme CSS directives. 2024-01-25 18:17:54 +00:00
flash 4b2f9a2fec Fixed Ctrl+Enter submission not working anymore either. 2024-01-25 00:18:56 +00:00
flash ddb255bf32 Fixed forum post form throwing up the navigation confirmation when it isn't supposed to. 2024-01-25 00:12:53 +00:00
flash 5a70e3f3f1 Include SameSite attribute on cookies. 2024-01-24 22:14:48 +00:00
flash bd3e055323 Rewrote Javascript code. 2024-01-24 21:53:26 +00:00
flash dba5754ccc Fixed error when trying to add a new change. 2024-01-24 18:28:13 +00:00
flash ec6ba3f781 Imported new asset build script. 2024-01-24 18:24:40 +00:00
flash 70ec285f99 Added links to Amimami repositories. 2024-01-18 20:31:08 +00:00
flash 77eadd5bde Adjusted CORS handling for emoticon endpoint. 2024-01-17 19:57:46 +00:00
flash f0fc735975 Updated browserlists. 2024-01-08 13:43:34 +00:00
flash adb80bad9e Added server side image map support. 2024-01-08 13:42:22 +00:00
flash f30cf41f86 Ported boolean attribute support. 2024-01-08 13:36:47 +00:00
flash b4f5dd0660 Removed broken CONSTRAINT from perms table creation. 2023-12-16 18:51:17 +00:00
flash 133e2f420c Fixed markdown styling issues. 2023-12-15 12:56:08 +00:00
flash bf65c95490 Updated highlight.js and created new code theme. 2023-12-15 12:47:01 +00:00
flash 7ef5994da4 Updated Sentry library to 4.0 in Misuzu. 2023-12-15 01:03:57 +00:00
flash 2b34bde413 Fixed error when trying to create a new role. 2023-12-02 02:57:46 +00:00
flash 432615508d Fixed undefined variable. 2023-11-26 22:23:47 +00:00
flash a4cc14e4c1 Libraries have been updated once more. 2023-11-20 19:10:47 +00:00
flash 65e695e9d9 git.flash.moe -> patchii.net 2023-11-20 19:04:59 +00:00
flash 2e6a84b46d Updated source.md. 2023-11-09 20:58:56 +00:00
flash 8f56174637 Supply super user status in auth data. 2023-11-07 14:38:53 +00:00
flash 19fbe59ddd Return to purple. 2023-11-01 09:36:49 +00:00
flash f7a571e551 moguu? 2023-10-21 23:54:41 +00:00
flash 5f57e3fdf4 Use SharpConfig format for the pre-database config. 2023-10-21 23:45:40 +00:00
flash c2836719c7 Updated to use Syokuhou config library. 2023-10-20 22:29:28 +00:00
flash 14c9a1d9f6 Fixed oversight on members list. 2023-10-18 10:16:32 +00:00
flash 4f1e35b566 Fixed overly eager url encoding on the search page. 2023-10-18 10:11:21 +00:00
flash 9aa2a1431e Enable Spookii 2023-10-01 18:44:59 +00:00
flash 4322f2561c Fixed chat routes being broken. 2023-09-11 20:36:20 +00:00
flash 67d9620037 Fixed legacy paths being too / tolerant. 2023-09-11 20:15:48 +00:00
flash 904d220582 Fixed router related explosions. 2023-09-11 20:10:37 +00:00
flash d9b152fb78 Fixed oversight on memberlist. 2023-09-11 19:19:19 +00:00
flash a945cc518a Fixed syntax error in post.php. 2023-09-11 19:18:10 +00:00
flash edc64b45ff Fixed error when trying to view a non-existent topic when logged out. 2023-09-10 21:04:10 +00:00
flash 17e0d1f591 Added Sentry error logging on the server side. 2023-09-10 20:46:58 +00:00
flash 5554c5c28d Removed unused pagination helper function. 2023-09-10 20:12:27 +00:00
flash 55e23c7b5d Fixed CSRF tokens not being added to URLs that need them. 2023-09-10 20:02:11 +00:00
flash e376671136 Attempt at fixing forum issues. 2023-09-10 19:13:36 +00:00
flash 3e49f6e503 Added URL registry attributes. 2023-09-10 00:04:53 +00:00
flash 7db43a2acd Revert "チルノの日"
This reverts commit 099bd899ed.
2023-09-09 11:54:33 +00:00
flash 099bd899ed チルノの日 2023-09-08 23:07:37 +00:00
flash 1248c0d2f6 Moved various .php file redirects into the LegacyRouter. 2023-09-08 20:47:54 +00:00
flash c3bed1c0e3 Rewrote URL registry. 2023-09-08 20:40:48 +00:00
flash 163da8b213 Added separate context class for forum stuff and split up handling of each object type. 2023-09-08 13:22:46 +00:00
flash c68279add9 Cleaned up some things I missed. 2023-09-08 01:05:17 +00:00
flash 737c99280e Make PHPStan happy. 2023-09-08 00:54:19 +00:00
flash 8b0f960c86 Split auth stuff off into own context. 2023-09-08 00:43:00 +00:00
flash c5a284f360 Route registration with attributes! 2023-09-08 00:13:30 +00:00
flash 506d32d210 Fixed incorrect type on latest forum post fetching result. 2023-09-07 20:53:19 +00:00
flash 498ec0cf9a Merge SharpChat permission set into the Misuzu permission system directly. 2023-09-06 20:44:28 +00:00
flash 15e96684c2 Moved authentication related macros out of MisuzuContext. 2023-09-06 20:06:07 +00:00
flash 73e4597e16 Rewrote Satori recent forum post fetch. 2023-09-06 19:35:50 +00:00
flash 9b2c409a24 Moved user related stuff into its own context object. 2023-09-06 13:50:19 +00:00
flash 7190a5f4df Syntactic sugar for mass route registration. 2023-09-06 11:59:44 +00:00
flash 5c67d49225 Fixed edit display threshold. 2023-09-06 11:32:13 +00:00
flash 69e4d05be6 Pluralise Views. 2023-09-06 11:19:54 +00:00
flash 2d0f083e1a Fixed topic read status check. 2023-09-06 11:19:04 +00:00
flash 1da6470928 Switch to Sasae. 2023-08-31 21:33:34 +00:00
flash 9682fa595a Fixed static analysis detections. 2023-08-31 17:14:41 +00:00
flash c14195c4c3 Moved render_info and render_error into Template class. 2023-08-31 15:59:53 +00:00
flash 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
flash 0c9bac473b No longer rely on Referer header for the comments return URL. 2023-08-31 14:39:50 +00:00
flash 061d4c8a8f Fixed leaderboard name not retaining the leading 0. 2023-08-31 00:54:17 +00:00
flash 6fc10984e1 Append total posts count at the end of the leaderboard. 2023-08-31 00:52:14 +00:00
flash e222009dd0 Fixed oversight. 2023-08-31 00:40:07 +00:00
flash 85b629bc08 Fixed missing use statement. 2023-08-31 00:38:20 +00:00
flash 16ea495c7a Added permission for displaying load timings in the footer. 2023-08-31 00:37:09 +00:00
flash ad3fe74275 Removed old database backend. 2023-08-31 00:31:11 +00:00
flash 29426fafc1 Count profile stats using Index database backend. 2023-08-31 00:24:59 +00:00
flash 4d6fb64f3a Added shitty search hack to users class. 2023-08-31 00:19:20 +00:00
flash 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
flash f03c8ebfa5 Moved validation methods into the new Users class. 2023-08-30 23:41:44 +00:00
flash 07a2868159 Rewrote permissions system. 2023-08-30 22:37:21 +00:00
flash ca23822e40 Fixed errors on profiles. 2023-08-28 14:45:32 +00:00
flash 34bd71600a Removed manage.php. 2023-08-28 13:45:36 +00:00
flash 5bab957a7c Fixed user colours in comments sections. 2023-08-28 13:33:39 +00:00
flash 57b9e82c10 Fixed topic type string usage. 2023-08-28 01:41:13 +00:00
flash 460a0ca57d Fixed user colours not showing on forum posts. 2023-08-28 01:32:05 +00:00
flash 39c6269cf3 Rewrote forum backend. 2023-08-28 01:17:34 +00:00
flash fb41c71ee9 Fixed emoticon ordering in chat. 2023-08-07 12:59:08 +00:00
flash 2214dffc5b Fixed profile editing failing due to old argument. 2023-08-06 19:09:59 +00:00
flash bab8b29c5b Fixed error 500 when trying to log in to a non-existing user. 2023-08-06 18:22:39 +00:00
flash 0a11c5525a Fixed oversight regarding RNG ordering of user list. 2023-08-05 13:55:34 +00:00
flash d4f6990e8a Made data source argument lists for News, Changelog, Comments and Emotes consistent with the rest. 2023-08-05 13:50:15 +00:00
flash 87915b6a25 Fixed forum post deletion and editing. 2023-08-04 22:49:09 +00:00
flash cf71129153 Converted all Misuzu style route handlers to Index style ones. 2023-08-04 20:51:02 +00:00
flash 6bfa3d7238 Fixed error 500 when viewing profiles as guest. 2023-08-04 17:44:37 +00:00
flash b7de5acfd8 Fixed search and updated collations of various fields to more appropriate ones. 2023-08-03 12:40:37 +00:00
flash 9dd7156c79 Fixed issue caused by used of dangling variable on sessions page. 2023-08-03 01:43:43 +00:00
flash 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
flash 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
flash 57081d858d Added server side stuff for Satori hooks. 2023-07-29 22:18:20 +00:00
flash e813f2a90e Some TOTP touch-ups. 2023-07-29 20:18:41 +00:00
flash 0158333c90 Removed permissions stuff from the User object. 2023-07-29 18:15:30 +00:00
flash a89d8d26f4 Fixed error when news comments category doesn't exist somehow. 2023-07-29 18:01:41 +00:00
flash e3c0ae662e Removed HasRankInterface. 2023-07-29 17:31:43 +00:00
flash 61daa21d3a Emit audit log upon impersonation. 2023-07-28 23:23:45 +00:00
flash 934b016541 Added counters table for storing numbers of things statically. 2023-07-28 23:17:37 +00:00
flash 8ef113f3a9 Allow non-super users to impersonate select users. 2023-07-28 21:20:19 +00:00
flash a22433f7dd Don't update last online time and ip address when impersonating. 2023-07-28 20:43:08 +00:00
flash c5ec94289d Added notice when there's no account logs to display. 2023-07-28 20:36:16 +00:00
flash 8c52fc81e2 Hide roles section from settings if there's only one available. 2023-07-28 20:33:44 +00:00
flash d2f0eebfb2 Use random alphabetic string instead hex bytes for session tokens. 2023-07-28 20:13:11 +00:00
flash 3148da4403 Rewrote Sessions backend. 2023-07-28 20:06:12 +00:00
flash 5c8ffa09fc Cleaned up User and UserSession queries. 2023-07-28 15:07:30 +00:00
flash 20b309563e Fixed phpstan detections. 2023-07-27 23:49:55 +00:00
flash 461ffbf73b Rewrote user role handling. 2023-07-27 23:26:05 +00:00
flash 26a0e11253 Fixed data export. 2023-07-27 13:14:32 +00:00
flash 70623d3a7c Pluralise user role relations table name. 2023-07-27 13:09:22 +00:00
flash b4d4e8578c Rewrote TFA session code. 2023-07-27 12:44:50 +00:00
flash 8480d5f043 Fixed the manage index statistics causing a 500 because the old warnings table is Gone. 2023-07-26 22:57:03 +00:00
flash a30df1b17c Fixed warning deletion. 2023-07-26 22:48:47 +00:00
flash 351043e283 Split Sharp Chat kick and ban permissions based on the Misuzu warnings and bans permissions. 2023-07-26 22:46:35 +00:00
flash 2231cd8124 Rewrote user warnings backend. 2023-07-26 22:43:50 +00:00
flash 86432616c6 Expiration -> Expires 2023-07-26 18:24:49 +00:00
flash 1d552e907b Added new banning system.
it actually works and isn't confusing this time around!
2023-07-26 18:19:48 +00:00
flash 057551edb3 Pluralise. 2023-07-26 11:56:06 +00:00
flash 710049794f Fixed typo that would cause things to fail. 2023-07-26 11:54:49 +00:00
flash ca1edb4270 Fixed gross misalignment. 2023-07-25 19:03:48 +00:00
flash f4f465d8d8 Redesigned news post preview information section. 2023-07-25 19:02:00 +00:00
flash 81f4dfce19 Fixed error 500 when trying to view a non-existent profile. 2023-07-25 15:03:25 +00:00
flash 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
flash 3299d73df2 Added new moderator notes system. 2023-07-25 14:40:31 +00:00
flash 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
flash 3d67b59238 Attempt 2 at fixing the profile fields issue (this one actually fixes the issue!) 2023-07-22 21:25:51 +00:00
flash dd21fce6e3 Rewrote password recovery token storage using new DB backend. 2023-07-22 21:20:03 +00:00
flash f6058823f1 Fixed error 500 on profiles when filling certain fields in specific conditions. 2023-07-22 20:54:52 +00:00
flash 392881c0d8 Fixed type on getUserId in LoginAttemptInfo. 2023-07-22 17:27:42 +00:00
flash 6e3023a772 Rewrite login attempts log to use new database backend. 2023-07-22 16:37:57 +00:00
flash 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
flash 42d893fc18 Use the Index DbStatementCache implementation. 2023-07-22 14:00:51 +00:00
flash baefea88df Use the Index DbTools version for list prepare thing. 2023-07-22 13:54:42 +00:00
flash e369038609 Updated Index Serialiser usage. 2023-07-21 21:56:09 +00:00
flash 9962bbc5df Added phpstan as a dev dependency. 2023-07-21 19:38:54 +00:00
flash 761bc94b8e Removed local config plugin and fixed Index info pages. 2023-07-21 19:30:28 +00:00
flash ffbe25d0b5 Oops it's all white! 2023-07-21 19:17:57 +00:00
flash e4b647f2c6 Updated project licence to BSD3CC and import Index through Composer. 2023-07-21 18:58:37 +00:00
flash 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
flash 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
flash ebac064c59 Fixed error 500 on logs and sessions pages because of dead library. 2023-07-21 11:33:27 +00:00
flash f32624c61d Improved profile fields code. 2023-07-20 19:36:43 +00:00
flash 2e49940260 Upgrade to PHP 8.2. 2023-07-19 19:10:20 +00:00
flash 24d61cc60e Removed lockdown feature for now. 2023-07-19 19:04:57 +00:00
flash 029c1ff20e Restructured public folder and initialisation process. 2023-07-19 19:03:53 +00:00
flash c9993bf08b Display full join and seen dates on hover. 2023-07-19 18:18:27 +00:00
flash e678efedf4 Minor members list redesign. 2023-07-19 18:14:04 +00:00
flash 239b0bae61 Removed overbearing global shadow. 2023-07-19 14:43:49 +00:00
flash 30e77bd698 Removed leftover abstract class. 2023-07-19 14:34:02 +00:00
flash 65549e3fa4 Fixed whatever the date formatter was smoking. 2023-07-18 23:19:19 +00:00
flash 319f37a313 Removed server-side relative time. 2023-07-18 23:12:47 +00:00
flash bec58f589f Removed unnecessary checks from URL formatter. 2023-07-18 22:36:07 +00:00
flash 473d5f22b5 Removed old formats of and unused SharpChat endpoints. 2023-07-18 22:33:13 +00:00
flash e6c826a7d7 Fixed various errors and oversights caught by phpstan. 2023-07-18 22:24:23 +00:00
flash 2f7cddde19 Config class overhaul. 2023-07-18 21:48:44 +00:00
flash cecfaf4852 Removed timeago library. 2023-07-17 20:14:21 +00:00
flash e5d9128cd0 Fixed account data export memory usage. 2023-07-17 19:28:13 +00:00
flash 1a11a8f8ba Rewrote audit log on new database backend. 2023-07-17 17:43:17 +00:00
flash 96be282a93 Fixed Javascript not working because it's written very poorly. 2023-07-17 14:44:09 +00:00
flash 074e078692 Use Node for asset building instead of building on the fly every time (feat. minification!) 2023-07-17 14:37:54 +00:00
flash f24f811acc Rewrote most of the comments backend.g 2023-07-15 23:58:17 +00:00
flash 6274f7f8d3 Fixed some routing oversights. 2023-07-15 17:45:39 +00:00
flash 472fc0decc Show Index and PDO query counts separately in the footer. 2023-07-15 17:15:40 +00:00
flash bff42c26ab Rewrote the news backend. 2023-07-15 17:02:46 +00:00
flash 69c6b6f2ac Fixed various other oversights. 2023-07-15 02:14:39 +00:00
flash c56617e051 Fixed error on main page. 2023-07-15 02:08:13 +00:00
flash 76c9cc50f4 Rewrote the Changelog code. 2023-07-15 02:05:49 +00:00
flash 6d0d49171e Added more elegant method for statement caching. 2023-07-14 20:26:38 +00:00
flash 3e2183b7b2 Fixed leap year birthdays without a year set. 2023-07-12 23:08:35 +00:00
flash 3909cdf762 Rewrote backend for emoticons.
Manage actually works this time!!!
2023-07-12 21:52:55 +00:00
flash 9b65ce005a Fixed possible NULL in CSRF check. 2023-07-12 19:14:40 +00:00
flash 29165de457 Use the Index DSN to create the PDO based DB instance. 2023-07-11 22:45:23 +00:00
flash 1186b0daeb Use Index for CSRF protection tokens. 2023-07-11 22:13:56 +00:00
flash ba8115fe10 CSRF and URL cleanup. 2023-07-11 20:51:24 +00:00
flash f025ee13d0 Rely on NGINX GeoIP2 module for country code lookup. 2023-07-11 00:25:43 +00:00
flash 575b5e8271 Updated info pages. 2023-07-10 23:07:48 +00:00
flash 69d04a7929 Switched to a tools directory for commands. 2023-07-10 22:52:30 +00:00
flash 9cb0a04611 Get rid of unused JSON stuff. 2023-07-10 20:12:20 +00:00
flash 9feb6bcb66 Fixed country name not having a value for XX or any other fallback. 2023-07-05 23:12:44 +00:00
flash 3507ae61ff Switched to Index byte formatter and adjusted max file sizes. 2023-07-05 23:09:28 +00:00
flash 191ef06ef3 Added local country list instead. 2023-07-05 02:23:34 +00:00
flash 027ed5aff6 Cleaned up various utility functions. 2023-07-05 01:33:12 +00:00
flash 1bb9bd6541 Apply user colour to header rather than username on profiles. 2023-07-03 13:53:58 +00:00
flash b5b4bf6b5a Fixed birthdate setting not working (did it ever work???). 2023-05-26 18:41:21 +00:00
flash 0bb1303413 Updated authentication token format. 2023-05-21 18:15:04 +00:00
flash 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
flash 8038f61470 Added ability to add redirects to deleted topic ids. 2023-04-30 00:18:14 +00:00
flash 6f679fc78c Fixed oversights that occur because of the empty username. 2023-04-29 21:57:21 +00:00
flash c06993ff1d Removed space inserted before embed tags inserted by EEPROM. 2023-03-15 10:58:55 +00:00
flash 11ff8b5be1 Removed quirky newline. 2023-03-11 22:28:57 +00:00
flash d54528f8ea Gave posts a 1 minute cooldown for edits without being marked as edited. 2023-03-11 22:28:10 +00:00
flash d05046ff1f Removed Twitter integrations. 2023-03-09 21:38:03 +00:00
flash 521a8fb0d1 Added rudimentary EEPROM file uploading support to the forum post editor. 2023-03-09 21:05:37 +00:00
flash e909b2ffda Added editor buttons for video and audio in markdown mode. 2023-03-09 16:27:43 +00:00
flash a04df5cb43 Updated composter packages. 2023-03-09 16:23:42 +00:00
flash 9983233184 Allow media linking without https: or http: prefix on forum. 2023-03-09 16:18:52 +00:00
flash c7ed6ba511 Fixed smart event. 2023-02-24 18:36:32 +00:00
flash 5760e15df5 Added h1 thru h6 bbcodes. 2023-02-12 03:50:08 +00:00
flash d423c53cde Added most active forum category and topic to profiles. 2023-02-10 09:04:15 +00:00
flash b9b80e17d0 Sharp Chat interop updates. 2023-02-08 00:06:15 +00:00
flash 18c836a457 Made Twitter and Chat link targets in the header configurable. 2023-01-31 16:21:19 +00:00
flash af6d4aff3a Forum post text style fixes. 2023-01-29 21:34:22 +00:00
flash 03a0dcd948 Enabled video and audio embeds in markdown. 2023-01-29 21:06:03 +00:00
flash e6e5c873f6 Audio embed previews (no player yet). 2023-01-29 20:29:20 +00:00
flash a4be74cae3 constipation moment 2023-01-29 03:35:45 +00:00
flash e1122fb6b9 Improved video embed handling. 2023-01-29 01:51:54 +00:00
flash 48ce465893 Fixed various video embedding bugs. 2023-01-26 22:51:33 +00:00
flash 9dae77628d Removed will-change statements because buggy in Chrome. 2023-01-26 08:49:19 +00:00
flash 58edc5c5dc Fixed videos not embedding in the posting preview. 2023-01-25 23:03:38 +00:00
flash 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
flash 6727abe6c3 Fixed 'view full profile' thing showing up on non-existent users while logged out. 2023-01-07 04:47:31 +00:00
flash 047d225669 Fixed inability to log in with two factor authentication. 2023-01-07 04:46:49 +00:00
flash 37eea64a27 Updated database migration system to use the Index methods. 2023-01-07 04:15:19 +00:00
flash 5a4094867f Use interface constants instead of a dedicate enum class for config types. 2023-01-06 20:50:41 +00:00
flash 5a7f4765ab Changed name of context class and global variable. 2023-01-06 20:35:03 +00:00
flash e8518fde65 Updated handler classes to use the new IRouter interface. 2023-01-06 20:22:03 +00:00
flash 338945d01e Removed unused tester permission. 2023-01-06 00:03:29 +00:00
flash 56a9192f53 Store forum permission types as numbers rather than bit shifts. 2023-01-06 00:02:40 +00:00
flash 8bb8a6b6a5 Removed error to exception conversion in Misuzu (handled in Index). 2023-01-05 23:54:27 +00:00
flash a311de6acf Updates to GeoIP lookup stuff. 2023-01-05 20:03:26 +00:00
flash f168aceb03 Updated composer libraries. 2023-01-05 18:35:07 +00:00
flash 2394492bf8 Remove IPAddress::remote and all implicit resolving of the request remote address. 2023-01-05 18:33:03 +00:00
flash f7fcd3230a Removed IPAddress methods only used by the blacklist. 2023-01-05 17:15:26 +00:00
flash 05766f00e0 Removed IP blacklist for now. 2023-01-05 15:56:36 +00:00
flash eafdc28d5e Rewrote Twitter connection (v1.1 -> v2). 2023-01-05 03:20:31 +00:00
flash cb40fdc7c4 Fixed error when trying to use the forum posting form. 2023-01-03 00:31:39 +00:00
flash ebabb19998 Rewrote avatar element contruction as Twig macro. 2023-01-03 00:10:28 +00:00
flash 47121897b9 Updated copyright year. 2023-01-02 23:52:40 +00:00
flash 4f3d0c5246 Replaced Misuzu Colour library with the Index ones. 2023-01-02 23:48:04 +00:00
flash f9d2ca2bb5 Removed more XHR leftovers. 2023-01-02 23:12:23 +00:00
flash 053109fe4f Removed XHR stuff from comments handler. 2023-01-02 22:59:24 +00:00
flash d9c3ca1e5a "Fixed" user editor in the broom closet. 2023-01-02 20:09:38 +00:00
flash ed2201090c Pruned a lot of existing Javascript, comments will receive and overhaul later. 2023-01-02 20:07:55 +00:00
flash 5a495ec472 Fixed Mark As Read on forum index not working. 2023-01-02 19:50:33 +00:00
flash b451e87fa5 Updated contact info. 2023-01-02 18:41:47 +00:00
flash 7b37205c3d Fixed error when trying to edit profile. 2023-01-02 03:27:20 +00:00
flash ef05ad5b9c Fixed oversight from removing the proxy stuff. 2023-01-01 20:37:15 +00:00
flash f45dc55d48 Use Git HEAD hash for the template cache folder name. 2023-01-01 20:33:32 +00:00
flash 08f8f59fe6 Removed unused built-in media proxy. 2023-01-01 20:27:25 +00:00
flash 4f35e5e487 Restructured config handler. 2023-01-01 20:23:53 +00:00
flash 525ced6e4e Index updates + floatval, intval -> casts. 2023-01-01 19:06:01 +00:00
flash aef7297bee Removed unfinished leftovers of priority voting and polls. 2023-01-01 05:01:18 +00:00
flash cd959b7e55 Forgot to CTRL+S this file, oops! 2023-01-01 03:50:41 +00:00
flash 9efe8e6853 Removed support for rolling back database migrations. 2023-01-01 03:42:18 +00:00
618 changed files with 33890 additions and 22713 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

12
.gitignore vendored
View file

@ -1,10 +1,18 @@
# 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
@ -37,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,156 +0,0 @@
var Misuzu = function() {
if(Misuzu.initialised)
throw 'Misuzu script has already initialised.';
Misuzu.started = true;
console.log(
"%cMisuzu%c\nhttps://github.com/flashwave/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();
Misuzu.Forum.Polls.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,49 +0,0 @@
Misuzu.Forum.Polls = {};
Misuzu.Forum.Polls.init = function() {
var polls = document.getElementsByClassName('js-forum-poll');
if(!polls.length)
return;
for(var i = 0; i < polls.length; ++i)
Misuzu.Forum.Polls.initPoll(polls[i]);
};
Misuzu.Forum.Polls.initPoll = function() {
var options = poll.getElementsByClassName('input__checkbox__input'),
votesRemaining = poll.querySelector('.js-forum-poll-remaining'),
votesRemainingCount = poll.querySelector('.js-forum-poll-remaining-count'),
votesRemainingPlural = poll.querySelector('.js-forum-poll-remaining-plural'),
maxVotes = parseInt(poll.dataset.pollMaxVotes);
if(maxVotes < 2)
return;
var votes = maxVotes;
for(var i = 0; i < options.length; ++i) {
if(options[i].checked) {
if(votes < 1)
options[i].checked = false;
else
votes--;
}
options[i].addEventListener('change', function(ev) {
if(this.checked) {
if(votes < 1) {
this.checked = false;
ev.preventDefault();
return;
}
votes--;
} else
votes++;
votesRemainingCount.textContent = votes.toString();
votesRemainingPlural.hidden = votes == 1;
});
}
votesRemaining.hidden = false;
votesRemainingCount.textContent = votes.toString();
votesRemainingPlural.hidden = votes == 1;
};

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 {

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