more stuff
This commit is contained in:
parent
95f431a7d4
commit
a0805cc29b
16 changed files with 280 additions and 205 deletions
|
@ -75,11 +75,11 @@ class BBcode
|
||||||
['s', '<del>{param}</del>'],
|
['s', '<del>{param}</del>'],
|
||||||
['spoiler', '<span class="spoiler">{param}</span>'],
|
['spoiler', '<span class="spoiler">{param}</span>'],
|
||||||
['box', '<div class="spoiler-box-container">
|
['box', '<div class="spoiler-box-container">
|
||||||
<div class="spoiler-box-title" onclick="Sakura.toggleClass(this.parentNode.children[1], \'hidden\');">
|
<div class="spoiler-box-title" onclick="Sakura.toggleClass(this.parentNode.children[1], \'hidden\');">'
|
||||||
Click to open</div><div class="spoiler-box-content hidden">{param}</div></div>', ],
|
. 'Click to open</div><div class="spoiler-box-content hidden">{param}</div></div>'],
|
||||||
['box', '<div class="spoiler-box-container"><div class="spoiler-box-title"
|
['box', '<div class="spoiler-box-container"><div class="spoiler-box-title"'
|
||||||
onclick="Sakura.toggleClass(this.parentNode.children[1], \'hidden\');">{option}</div>
|
. ' onclick="Sakura.toggleClass(this.parentNode.children[1], \'hidden\');">{option}</div>'
|
||||||
<div class="spoiler-box-content hidden">{param}</div></div>', ],
|
. '<div class="spoiler-box-content hidden">{param}</div></div>'],
|
||||||
['quote', '<blockquote><div class="quotee">Quote</div><div class="quote">{param}</div></blockquote>'],
|
['quote', '<blockquote><div class="quotee">Quote</div><div class="quote">{param}</div></blockquote>'],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -36,10 +36,12 @@ class Code extends CodeDefinition
|
||||||
*/
|
*/
|
||||||
public function asHtml(ElementNode $el)
|
public function asHtml(ElementNode $el)
|
||||||
{
|
{
|
||||||
return preg_replace(
|
$content = "";
|
||||||
"#\n*\[code\]\n*(.*?)\n*\[/code\]\n*#s",
|
|
||||||
'<pre class="code"><code>\\1</code></pre>',
|
foreach ($el->getChildren() as $child) {
|
||||||
$el->getAsBBCode()
|
$content .= $child->getAsBBCode();
|
||||||
);
|
}
|
||||||
|
|
||||||
|
return "<pre class='code'><code>{$content}</code></pre>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ namespace Sakura\Controllers;
|
||||||
|
|
||||||
use Sakura\Config;
|
use Sakura\Config;
|
||||||
use Sakura\DB;
|
use Sakura\DB;
|
||||||
|
use Sakura\Notification;
|
||||||
|
use Sakura\Perms\Site;
|
||||||
use Sakura\Rank;
|
use Sakura\Rank;
|
||||||
use Sakura\Router;
|
use Sakura\Router;
|
||||||
use Sakura\Template;
|
use Sakura\Template;
|
||||||
|
@ -104,7 +106,7 @@ class UserController extends Controller
|
||||||
global $currentUser;
|
global $currentUser;
|
||||||
|
|
||||||
// Check permission
|
// Check permission
|
||||||
if (!$currentUser->permission(\Sakura\Perms\Site::VIEW_MEMBERLIST)) {
|
if (!$currentUser->permission(Site::VIEW_MEMBERLIST)) {
|
||||||
return Template::render('global/restricted');
|
return Template::render('global/restricted');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,4 +138,42 @@ class UserController extends Controller
|
||||||
// Render the template
|
// Render the template
|
||||||
return Template::render('main/memberlist');
|
return Template::render('main/memberlist');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function notifications()
|
||||||
|
{
|
||||||
|
// TODO: add friend on/offline messages
|
||||||
|
global $currentUser;
|
||||||
|
|
||||||
|
// Set json content type
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
|
return json_encode(
|
||||||
|
$currentUser->notifications(),
|
||||||
|
JSON_FORCE_OBJECT | JSON_NUMERIC_CHECK | JSON_BIGINT_AS_STRING
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function markNotification($id = 0)
|
||||||
|
{
|
||||||
|
global $currentUser;
|
||||||
|
|
||||||
|
// Check permission
|
||||||
|
if ($currentUser->permission(Site::DEACTIVATED)) {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the notification object
|
||||||
|
$alert = new Notification($id);
|
||||||
|
|
||||||
|
// Verify that the currently authed user is the one this alert is for
|
||||||
|
if ($alert->user !== $currentUser->id) {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle the read status and save
|
||||||
|
$alert->toggleRead();
|
||||||
|
$alert->save();
|
||||||
|
|
||||||
|
return '1';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
81
libraries/Notification.php
Normal file
81
libraries/Notification.php
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Notification object.
|
||||||
|
*
|
||||||
|
* @package Sakura
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Sakura;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification!
|
||||||
|
*
|
||||||
|
* @package Sakura
|
||||||
|
* @author Julian van de Groep <me@flash.moe>
|
||||||
|
*/
|
||||||
|
class Notification
|
||||||
|
{
|
||||||
|
public $id = 0;
|
||||||
|
public $user = 0;
|
||||||
|
public $time = 0;
|
||||||
|
public $read = false;
|
||||||
|
public $title = "Notification";
|
||||||
|
public $text = "";
|
||||||
|
public $link = "";
|
||||||
|
public $image = "";
|
||||||
|
public $timeout = 0;
|
||||||
|
|
||||||
|
public function __construct($id = 0)
|
||||||
|
{
|
||||||
|
// Get notification data from the database
|
||||||
|
$data = DB::table('notifications')
|
||||||
|
->where('alert_id', $id)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
// Check if anything was returned and assign data
|
||||||
|
if ($data) {
|
||||||
|
$data = $data[0];
|
||||||
|
|
||||||
|
$this->id = $data->alert_id;
|
||||||
|
$this->user = $data->user_id;
|
||||||
|
$this->time = $data->alert_timestamp;
|
||||||
|
$this->read = intval($data->alert_read) !== 0;
|
||||||
|
$this->title = $data->alert_title;
|
||||||
|
$this->text = $data->alert_text;
|
||||||
|
$this->link = $data->alert_link;
|
||||||
|
$this->image = $data->alert_img;
|
||||||
|
$this->timeout = $data->alert_timeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
// Create submission data, insert and update take the same format
|
||||||
|
$data = [
|
||||||
|
'user_id' => $this->user,
|
||||||
|
'alert_timestamp' => $this->time,
|
||||||
|
'alert_read' => $this->read ? 1 : 0,
|
||||||
|
'alert_title' => $this->title,
|
||||||
|
'alert_text' => $this->text,
|
||||||
|
'alert_link' => $this->link,
|
||||||
|
'alert_img' => $this->image,
|
||||||
|
'alert_timeout' => $this->timeout,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Update if id isn't 0
|
||||||
|
if ($this->id) {
|
||||||
|
DB::table('notifications')
|
||||||
|
->where('alert_id', $this->id)
|
||||||
|
->update($data);
|
||||||
|
} else {
|
||||||
|
$this->id = DB::table('notifications')
|
||||||
|
->insertGetId($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toggleRead()
|
||||||
|
{
|
||||||
|
// Set read to the negative value of itself
|
||||||
|
$this->read = !$this->read;
|
||||||
|
}
|
||||||
|
}
|
|
@ -136,8 +136,6 @@ class Router
|
||||||
*
|
*
|
||||||
* @param array $filters The filters for this group.
|
* @param array $filters The filters for this group.
|
||||||
* @param \Closure $callback The containers
|
* @param \Closure $callback The containers
|
||||||
*
|
|
||||||
* @return string The generated URI.
|
|
||||||
*/
|
*/
|
||||||
public static function group($filters, $callback)
|
public static function group($filters, $callback)
|
||||||
{
|
{
|
||||||
|
@ -145,6 +143,17 @@ class Router
|
||||||
self::$router->group($filters, $callback);
|
self::$router->group($filters, $callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create filter.
|
||||||
|
*
|
||||||
|
* string $name Identifier of the filter
|
||||||
|
* \Closure $method
|
||||||
|
*/
|
||||||
|
public static function filter($name, $method)
|
||||||
|
{
|
||||||
|
self::$router->filter($name, $method);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle requests.
|
* Handle requests.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1194,4 +1194,35 @@ class User
|
||||||
// Return success
|
// Return success
|
||||||
return [1, 'SUCCESS'];
|
return [1, 'SUCCESS'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all the notifications for this user.
|
||||||
|
*
|
||||||
|
* @param int $timeDifference The timeframe of alerts that should be fetched.
|
||||||
|
* @param bool $excludeRead Whether alerts that are marked as read should be included.
|
||||||
|
*
|
||||||
|
* @return array An array with Notification objects.
|
||||||
|
*/
|
||||||
|
public function notifications($timeDifference = 0, $excludeRead = true)
|
||||||
|
{
|
||||||
|
$alertIds = DB::table('notifications')
|
||||||
|
->where('user_id', $this->id);
|
||||||
|
|
||||||
|
if ($timeDifference) {
|
||||||
|
$alertIds->where('alert_timestamp', '>', time() - $timeDifference);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($excludeRead) {
|
||||||
|
$alertIds->where('alert_read', 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$alertIds = array_column($alertIds->get(['alert_id']), 'alert_id');
|
||||||
|
$alerts = [];
|
||||||
|
|
||||||
|
foreach ($alertIds as $alertId) {
|
||||||
|
$alerts[$alertId] = new Notification($alertId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $alerts;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -350,92 +350,6 @@ class Users
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a user's notifications.
|
|
||||||
*
|
|
||||||
* @param int $uid The user id.
|
|
||||||
* @param int $timediff The maximum difference in time.
|
|
||||||
* @param bool $excludeRead Exclude notifications that were already read.
|
|
||||||
* @param bool $markRead Automatically mark as read.
|
|
||||||
*
|
|
||||||
* @return array The notifications.
|
|
||||||
*/
|
|
||||||
public static function getNotifications($uid = null, $timediff = 0, $excludeRead = true, $markRead = false)
|
|
||||||
{
|
|
||||||
// Prepare conditions
|
|
||||||
$uid = $uid ? $uid : self::checkLogin()[0];
|
|
||||||
$time = $timediff ? time() - $timediff : '%';
|
|
||||||
$read = $excludeRead ? '0' : '%';
|
|
||||||
|
|
||||||
// Get notifications for the database
|
|
||||||
$alerts = DB::table('notifications')
|
|
||||||
->where('user_id', $uid)
|
|
||||||
->where('alert_timestamp', '>', $time)
|
|
||||||
->where('alert_read', $read)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
// Mark the notifications as read
|
|
||||||
if ($markRead) {
|
|
||||||
// Iterate over all entries
|
|
||||||
foreach ($alerts as $alert) {
|
|
||||||
// If the notifcation is already read skip
|
|
||||||
if ($alert->alert_read) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark them as read
|
|
||||||
self::markNotificationRead($notification->alert_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the notifications
|
|
||||||
return $notifications;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark a notification as read
|
|
||||||
*
|
|
||||||
* @param mixed $id The notification's ID.
|
|
||||||
* @param mixed $mode Read or unread.
|
|
||||||
*/
|
|
||||||
public static function markNotificationRead($id, $mode = true)
|
|
||||||
{
|
|
||||||
// Execute an update statement
|
|
||||||
DB::table('notifications')
|
|
||||||
->where('alert_id', $id)
|
|
||||||
->update([
|
|
||||||
'alert_read' => ($mode ? 1 : 0),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new notification.
|
|
||||||
*
|
|
||||||
* @param int $user The user id.
|
|
||||||
* @param string $title The notification title.
|
|
||||||
* @param string $text The rest of the text.
|
|
||||||
* @param int $timeout After how many seconds the notification should disappear.
|
|
||||||
* @param string $img The image.
|
|
||||||
* @param string $link The link.
|
|
||||||
* @param int $sound Whether it should play a noise.
|
|
||||||
*/
|
|
||||||
public static function createNotification($user, $title, $text, $timeout = 60000, $img = 'FONT:fa-info-circle', $link = '', $sound = 0)
|
|
||||||
{
|
|
||||||
// Insert it into the database
|
|
||||||
DB::table('notifications')
|
|
||||||
->insert([
|
|
||||||
'user_id' => $user,
|
|
||||||
'alert_timestamp' => time(),
|
|
||||||
'alert_read' => 0,
|
|
||||||
'alert_sound' => ($sound ? 1 : 0),
|
|
||||||
'alert_title' => $title,
|
|
||||||
'alert_text' => $text,
|
|
||||||
'alert_link' => $link,
|
|
||||||
'alert_img' => $img,
|
|
||||||
'alert_timeout' => $timeout,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the newest member's ID.
|
* Get the newest member's ID.
|
||||||
*
|
*
|
||||||
|
|
|
@ -20,18 +20,18 @@ function notifyUI(content) {
|
||||||
alert.className = 'notification-enter';
|
alert.className = 'notification-enter';
|
||||||
alert.id = id;
|
alert.id = id;
|
||||||
// Add the icon
|
// Add the icon
|
||||||
if ((typeof content.img).toLowerCase() === 'undefined' || content.img == null || content.img.length < 2) {
|
if ((typeof content.image).toLowerCase() === 'undefined' || content.image == null || content.image.length < 2) {
|
||||||
aIconCont = document.createElement('div');
|
aIconCont = document.createElement('div');
|
||||||
aIconCont.className = 'font-icon fa fa-info fa-4x';
|
aIconCont.className = 'font-icon fa fa-info fa-4x';
|
||||||
}
|
}
|
||||||
else if (content.img.substr(0, 5) == 'FONT:') {
|
else if (content.image.substr(0, 5) == 'FONT:') {
|
||||||
aIconCont = document.createElement('div');
|
aIconCont = document.createElement('div');
|
||||||
aIconCont.className = 'font-icon fa ' + content.img.replace('FONT:', '') + ' fa-4x';
|
aIconCont.className = 'font-icon fa ' + content.image.replace('FONT:', '') + ' fa-4x';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
aIconCont = document.createElement('img');
|
aIconCont = document.createElement('img');
|
||||||
aIconCont.alt = id;
|
aIconCont.alt = id;
|
||||||
aIconCont.src = content.img;
|
aIconCont.src = content.image;
|
||||||
}
|
}
|
||||||
aIcon.appendChild(aIconCont);
|
aIcon.appendChild(aIconCont);
|
||||||
aIcon.className = 'notification-icon';
|
aIcon.className = 'notification-icon';
|
||||||
|
@ -58,25 +58,6 @@ function notifyUI(content) {
|
||||||
alert.appendChild(aClose);
|
alert.appendChild(aClose);
|
||||||
// Append the notification to the document
|
// Append the notification to the document
|
||||||
cont.appendChild(alert);
|
cont.appendChild(alert);
|
||||||
// Play sound if request
|
|
||||||
if (content.sound) {
|
|
||||||
// Create the elements
|
|
||||||
var sound = document.createElement('audio');
|
|
||||||
var mp3 = document.createElement('source');
|
|
||||||
var ogg = document.createElement('source');
|
|
||||||
// Assign attribs
|
|
||||||
mp3.type = 'audio/mp3';
|
|
||||||
ogg.type = 'audio/ogg';
|
|
||||||
mp3.src = sakuraVars.content + '/sounds/notify.mp3';
|
|
||||||
ogg.src = sakuraVars.content + '/sounds/notify.ogg';
|
|
||||||
// Append
|
|
||||||
sound.appendChild(mp3);
|
|
||||||
sound.appendChild(ogg);
|
|
||||||
// Less loud
|
|
||||||
sound.volume = 0.5;
|
|
||||||
// And play
|
|
||||||
sound.play();
|
|
||||||
}
|
|
||||||
// If keepalive is 0 keep the notification open forever
|
// If keepalive is 0 keep the notification open forever
|
||||||
if (content.timeout > 0) {
|
if (content.timeout > 0) {
|
||||||
// Set a timeout and close after an amount
|
// Set a timeout and close after an amount
|
||||||
|
@ -111,7 +92,7 @@ function notifyRequest(session) {
|
||||||
}
|
}
|
||||||
// Create AJAX object
|
// Create AJAX object
|
||||||
var get = new AJAX();
|
var get = new AJAX();
|
||||||
get.setUrl('/settings.php?request-notifications=true&time=' + Sakura.epoch() + '&session=' + session);
|
get.setUrl('/notifications');
|
||||||
// Add callbacks
|
// Add callbacks
|
||||||
get.addCallback(200, function () {
|
get.addCallback(200, function () {
|
||||||
// Assign the parsed JSON
|
// Assign the parsed JSON
|
||||||
|
|
|
@ -8,9 +8,8 @@ interface Notification {
|
||||||
title: string;
|
title: string;
|
||||||
text: string;
|
text: string;
|
||||||
link: string;
|
link: string;
|
||||||
img: string;
|
image: string;
|
||||||
timeout: number;
|
timeout: number;
|
||||||
sound: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawns a notification
|
// Spawns a notification
|
||||||
|
@ -29,22 +28,22 @@ function notifyUI(content: Notification): void {
|
||||||
var aCIcon: HTMLDivElement = document.createElement('div');
|
var aCIcon: HTMLDivElement = document.createElement('div');
|
||||||
var aClear: HTMLDivElement = document.createElement('div');
|
var aClear: HTMLDivElement = document.createElement('div');
|
||||||
var aIconCont: any;
|
var aIconCont: any;
|
||||||
|
|
||||||
// Add attributes to the main element
|
// Add attributes to the main element
|
||||||
alert.className = 'notification-enter';
|
alert.className = 'notification-enter';
|
||||||
alert.id = id;
|
alert.id = id;
|
||||||
|
|
||||||
// Add the icon
|
// Add the icon
|
||||||
if ((typeof content.img).toLowerCase() === 'undefined' || content.img == null || content.img.length < 2) {
|
if ((typeof content.image).toLowerCase() === 'undefined' || content.image == null || content.image.length < 2) {
|
||||||
aIconCont = document.createElement('div');
|
aIconCont = document.createElement('div');
|
||||||
aIconCont.className = 'font-icon fa fa-info fa-4x';
|
aIconCont.className = 'font-icon fa fa-info fa-4x';
|
||||||
} else if (content.img.substr(0, 5) == 'FONT:') {
|
} else if (content.image.substr(0, 5) == 'FONT:') {
|
||||||
aIconCont = document.createElement('div');
|
aIconCont = document.createElement('div');
|
||||||
aIconCont.className = 'font-icon fa ' + content.img.replace('FONT:', '') + ' fa-4x';
|
aIconCont.className = 'font-icon fa ' + content.image.replace('FONT:', '') + ' fa-4x';
|
||||||
} else {
|
} else {
|
||||||
aIconCont = document.createElement('img');
|
aIconCont = document.createElement('img');
|
||||||
aIconCont.alt = id;
|
aIconCont.alt = id;
|
||||||
aIconCont.src = content.img;
|
aIconCont.src = content.image;
|
||||||
}
|
}
|
||||||
|
|
||||||
aIcon.appendChild(aIconCont);
|
aIcon.appendChild(aIconCont);
|
||||||
|
@ -78,30 +77,6 @@ function notifyUI(content: Notification): void {
|
||||||
// Append the notification to the document
|
// Append the notification to the document
|
||||||
cont.appendChild(alert);
|
cont.appendChild(alert);
|
||||||
|
|
||||||
// Play sound if request
|
|
||||||
if (content.sound) {
|
|
||||||
// Create the elements
|
|
||||||
var sound: HTMLAudioElement = document.createElement('audio');
|
|
||||||
var mp3: HTMLSourceElement = document.createElement('source');
|
|
||||||
var ogg: HTMLSourceElement = document.createElement('source');
|
|
||||||
|
|
||||||
// Assign attribs
|
|
||||||
mp3.type = 'audio/mp3';
|
|
||||||
ogg.type = 'audio/ogg';
|
|
||||||
mp3.src = sakuraVars.content + '/sounds/notify.mp3';
|
|
||||||
ogg.src = sakuraVars.content + '/sounds/notify.ogg';
|
|
||||||
|
|
||||||
// Append
|
|
||||||
sound.appendChild(mp3);
|
|
||||||
sound.appendChild(ogg);
|
|
||||||
|
|
||||||
// Less loud
|
|
||||||
sound.volume = 0.5;
|
|
||||||
|
|
||||||
// And play
|
|
||||||
sound.play();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If keepalive is 0 keep the notification open forever
|
// If keepalive is 0 keep the notification open forever
|
||||||
if (content.timeout > 0) {
|
if (content.timeout > 0) {
|
||||||
// Set a timeout and close after an amount
|
// Set a timeout and close after an amount
|
||||||
|
@ -128,7 +103,7 @@ function notifyClose(id: string): void {
|
||||||
// Opening an alerted link
|
// Opening an alerted link
|
||||||
function notifyOpen(id: string): void {
|
function notifyOpen(id: string): void {
|
||||||
var sakuraHref: string = document.getElementById(id).getAttribute('sakurahref');
|
var sakuraHref: string = document.getElementById(id).getAttribute('sakurahref');
|
||||||
|
|
||||||
if ((typeof sakuraHref).toLowerCase() !== 'undefined') {
|
if ((typeof sakuraHref).toLowerCase() !== 'undefined') {
|
||||||
window.location.assign(sakuraHref);
|
window.location.assign(sakuraHref);
|
||||||
}
|
}
|
||||||
|
@ -143,7 +118,7 @@ function notifyRequest(session: string): void {
|
||||||
|
|
||||||
// Create AJAX object
|
// Create AJAX object
|
||||||
var get: AJAX = new AJAX();
|
var get: AJAX = new AJAX();
|
||||||
get.setUrl('/settings.php?request-notifications=true&time=' + Sakura.epoch() + '&session=' + session);
|
get.setUrl('/notifications');
|
||||||
|
|
||||||
// Add callbacks
|
// Add callbacks
|
||||||
get.addCallback(200, () => {
|
get.addCallback(200, () => {
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -17,7 +17,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
// Include components
|
// Include components
|
||||||
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . 'sakura.php';
|
require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . 'sakura.php';
|
||||||
|
|
||||||
// Notifications
|
// Notifications (decommissioned)
|
||||||
if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notifications']) {
|
if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notifications']) {
|
||||||
// Create the notification container array
|
// Create the notification container array
|
||||||
$notifications = [];
|
$notifications = [];
|
||||||
|
@ -28,20 +28,23 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
&& $_REQUEST['time'] > (time() - 1000)
|
&& $_REQUEST['time'] > (time() - 1000)
|
||||||
&& isset($_REQUEST['session']) && $_REQUEST['session'] == session_id()) {
|
&& isset($_REQUEST['session']) && $_REQUEST['session'] == session_id()) {
|
||||||
// Get the user's notifications from the past forever but exclude read notifications
|
// Get the user's notifications from the past forever but exclude read notifications
|
||||||
$userNotifs = Users::getNotifications(null, 0, true, true);
|
$alerts = $currentUser->notifications();
|
||||||
|
|
||||||
// Add the proper values to the array
|
// Add the proper values to the array
|
||||||
foreach ($userNotifs as $notif) {
|
foreach ($alerts as $alert) {
|
||||||
// Add the notification to the display array
|
// Add the notification to the display array
|
||||||
$notifications[$notif['alert_timestamp']] = [
|
$notifications[$alert->id] = [
|
||||||
'read' => $notif['alert_read'],
|
'read' => $alert->read,
|
||||||
'title' => $notif['alert_title'],
|
'title' => $alert->title,
|
||||||
'text' => $notif['alert_text'],
|
'text' => $alert->text,
|
||||||
'link' => $notif['alert_link'],
|
'link' => $alert->link,
|
||||||
'img' => $notif['alert_img'],
|
'img' => $alert->image,
|
||||||
'timeout' => $notif['alert_timeout'],
|
'timeout' => $alert->timeout,
|
||||||
'sound' => $notif['alert_sound'],
|
'sound' => $alert->sound,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
$alert->toggleRead();
|
||||||
|
$alert->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +74,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
'title' => $friend->username . ' is online.',
|
'title' => $friend->username . ' is online.',
|
||||||
'text' => '',
|
'text' => '',
|
||||||
'link' => '',
|
'link' => '',
|
||||||
'img' => '/a/' . $friend->id,
|
'img' => Router::route('file.avatar', $friend->id),
|
||||||
'timeout' => 2000,
|
'timeout' => 2000,
|
||||||
'sound' => false,
|
'sound' => false,
|
||||||
];
|
];
|
||||||
|
@ -87,7 +90,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
'title' => $friend->username . ' is offline.',
|
'title' => $friend->username . ' is offline.',
|
||||||
'text' => '',
|
'text' => '',
|
||||||
'link' => '',
|
'link' => '',
|
||||||
'img' => '/a/' . $friend->id,
|
'img' => Router::route('file.avatar', $friend->id),
|
||||||
'timeout' => 2000,
|
'timeout' => 2000,
|
||||||
'sound' => false,
|
'sound' => false,
|
||||||
];
|
];
|
||||||
|
@ -377,16 +380,20 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
if (array_key_exists($action[1], $notifStrings)) {
|
if (array_key_exists($action[1], $notifStrings)) {
|
||||||
// Get the current user's profile data
|
// Get the current user's profile data
|
||||||
$user = User::construct($currentUser->id);
|
$user = User::construct($currentUser->id);
|
||||||
|
$friend = User::construct($_REQUEST[(isset($_REQUEST['add']) ? 'add' : 'remove')]);
|
||||||
|
|
||||||
Users::createNotification(
|
$alert = new Notification;
|
||||||
$_REQUEST[(isset($_REQUEST['add']) ? 'add' : 'remove')],
|
|
||||||
sprintf($notifStrings[$action[1]][0], $user->username),
|
$alert->user = $friend->id;
|
||||||
$notifStrings[$action[1]][1],
|
$alert->time = time();
|
||||||
60000,
|
$alert->sound = true;
|
||||||
Router::route('file.avatar', $user->id),
|
$alert->title = sprintf($notifStrings[$action[1]][0], $user->username);
|
||||||
Router::route('user.profile', $user->id),
|
$alert->text = $notifStrings[$action[1]][1];
|
||||||
'1'
|
$alert->image = Router::route('file.avatar', $user->id);
|
||||||
);
|
$alert->timeout = 60000;
|
||||||
|
$alert->link = Router::route('user.profile', $user->id);
|
||||||
|
|
||||||
|
$alert->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1490,11 +1497,6 @@ if (Users::checkLogin()) {
|
||||||
$renderData['messages'] = [];
|
$renderData['messages'] = [];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Notification history
|
|
||||||
case 'notifications.history':
|
|
||||||
$renderData['alerts'] = array_reverse(Users::getNotifications(null, 0, false, true));
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Avatar and background sizes
|
// Avatar and background sizes
|
||||||
case 'appearance.avatar':
|
case 'appearance.avatar':
|
||||||
case 'appearance.background':
|
case 'appearance.background':
|
||||||
|
|
60
routes.php
60
routes.php
|
@ -6,6 +6,32 @@
|
||||||
// Define namespace
|
// Define namespace
|
||||||
namespace Sakura;
|
namespace Sakura;
|
||||||
|
|
||||||
|
// Check if logged out
|
||||||
|
Router::filter('logoutCheck', function () {
|
||||||
|
global $currentUser;
|
||||||
|
|
||||||
|
if ($currentUser->id !== 0) {
|
||||||
|
$message = "You must be logged out to do that!";
|
||||||
|
|
||||||
|
Template::vars(['page' => compact('message')]);
|
||||||
|
|
||||||
|
return Template::render('global/information');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check if logged in
|
||||||
|
Router::filter('loginCheck', function () {
|
||||||
|
global $currentUser;
|
||||||
|
|
||||||
|
if ($currentUser->id === 0) {
|
||||||
|
$message = "You must be logged in to do that!";
|
||||||
|
|
||||||
|
Template::vars(['page' => compact('message')]);
|
||||||
|
|
||||||
|
return Template::render('global/information');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Meta pages
|
// Meta pages
|
||||||
Router::get('/', 'MetaController@index', 'main.index');
|
Router::get('/', 'MetaController@index', 'main.index');
|
||||||
Router::get('/faq', 'MetaController@faq', 'main.faq');
|
Router::get('/faq', 'MetaController@faq', 'main.faq');
|
||||||
|
@ -13,16 +39,20 @@ Router::get('/search', 'MetaController@search', 'main.search');
|
||||||
Router::get('/p/{id}', 'MetaController@infoPage', 'main.infopage');
|
Router::get('/p/{id}', 'MetaController@infoPage', 'main.infopage');
|
||||||
|
|
||||||
// Auth
|
// Auth
|
||||||
Router::get('/login', 'AuthController@loginGet', 'auth.login');
|
Router::group(['before' => 'logoutCheck'], function () {
|
||||||
Router::post('/login', 'AuthController@loginPost', 'auth.login');
|
Router::get('/login', 'AuthController@loginGet', 'auth.login');
|
||||||
Router::get('/logout', 'AuthController@logout', 'auth.logout');
|
Router::post('/login', 'AuthController@loginPost', 'auth.login');
|
||||||
Router::get('/register', 'AuthController@registerGet', 'auth.register');
|
Router::get('/register', 'AuthController@registerGet', 'auth.register');
|
||||||
Router::post('/register', 'AuthController@registerPost', 'auth.register');
|
Router::post('/register', 'AuthController@registerPost', 'auth.register');
|
||||||
Router::get('/resetpassword', 'AuthController@resetPasswordGet', 'auth.resetpassword');
|
Router::get('/resetpassword', 'AuthController@resetPasswordGet', 'auth.resetpassword');
|
||||||
Router::post('/resetpassword', 'AuthController@resetPasswordPost', 'auth.resetpassword');
|
Router::post('/resetpassword', 'AuthController@resetPasswordPost', 'auth.resetpassword');
|
||||||
Router::get('/reactivate', 'AuthController@reactivateGet', 'auth.reactivate');
|
Router::get('/reactivate', 'AuthController@reactivateGet', 'auth.reactivate');
|
||||||
Router::post('/reactivate', 'AuthController@reactivatePost', 'auth.reactivate');
|
Router::post('/reactivate', 'AuthController@reactivatePost', 'auth.reactivate');
|
||||||
Router::get('/activate', 'AuthController@activate', 'auth.activate');
|
Router::get('/activate', 'AuthController@activate', 'auth.activate');
|
||||||
|
});
|
||||||
|
Router::group(['before' => 'loginCheck'], function () {
|
||||||
|
Router::get('/logout', 'AuthController@logout', 'auth.logout');
|
||||||
|
});
|
||||||
|
|
||||||
// News
|
// News
|
||||||
Router::group(['prefix' => 'news'], function () {
|
Router::group(['prefix' => 'news'], function () {
|
||||||
|
@ -37,9 +67,11 @@ Router::group(['prefix' => 'forum'], function () {
|
||||||
Router::group(['prefix' => 'post'], function () {
|
Router::group(['prefix' => 'post'], function () {
|
||||||
Router::get('/{id:i}', 'ForumController@post', 'forums.post');
|
Router::get('/{id:i}', 'ForumController@post', 'forums.post');
|
||||||
Router::get('/{id:i}/raw', 'ForumController@postRaw', 'forums.post.raw');
|
Router::get('/{id:i}/raw', 'ForumController@postRaw', 'forums.post.raw');
|
||||||
Router::get('/{id:i}/delete', 'ForumController@deletePost', 'forums.post.delete');
|
Router::group(['before' => 'loginCheck'], function () {
|
||||||
Router::post('/{id:i}/delete', 'ForumController@deletePost', 'forums.post.delete');
|
Router::get('/{id:i}/delete', 'ForumController@deletePost', 'forums.post.delete');
|
||||||
Router::post('/{id:i}/edit', 'ForumController@editPost', 'forums.post.edit');
|
Router::post('/{id:i}/delete', 'ForumController@deletePost', 'forums.post.delete');
|
||||||
|
Router::post('/{id:i}/edit', 'ForumController@editPost', 'forums.post.edit');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Thread
|
// Thread
|
||||||
|
@ -66,6 +98,8 @@ Router::group(['prefix' => 'members'], function () {
|
||||||
// User
|
// User
|
||||||
Router::get('/u/{id}', 'UserController@profile', 'user.profile');
|
Router::get('/u/{id}', 'UserController@profile', 'user.profile');
|
||||||
Router::get('/u/{id}/header', 'FileController@header', 'user.header');
|
Router::get('/u/{id}/header', 'FileController@header', 'user.header');
|
||||||
|
Router::get('/notifications', 'UserController@notifications', 'user.notifications');
|
||||||
|
Router::get('/notifications/{id}/mark', 'UserController@markNotification', 'user.notifications.mark');
|
||||||
|
|
||||||
// Files
|
// Files
|
||||||
Router::get('/a/{id}', 'FileController@avatar', 'file.avatar');
|
Router::get('/a/{id}', 'FileController@avatar', 'file.avatar');
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
namespace Sakura;
|
namespace Sakura;
|
||||||
|
|
||||||
// Define Sakura version
|
// Define Sakura version
|
||||||
define('SAKURA_VERSION', 20160325);
|
define('SAKURA_VERSION', 20160326);
|
||||||
|
|
||||||
// Define Sakura Path
|
// Define Sakura Path
|
||||||
define('ROOT', __DIR__ . '/');
|
define('ROOT', __DIR__ . '/');
|
||||||
|
|
|
@ -212,6 +212,12 @@
|
||||||
timeElems[timeElem].innerText = Sakura.timeElapsed(Math.floor(parsed / 1000));
|
timeElems[timeElem].innerText = Sakura.timeElapsed(Math.floor(parsed / 1000));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notifyRequest('{{ php.sessionid }}');
|
||||||
|
|
||||||
|
setInterval(function() {
|
||||||
|
notifyRequest('{{ php.sessionid }}');
|
||||||
|
}, 60000);
|
||||||
</script>
|
</script>
|
||||||
{% if sakura.dev.showChangelog and stats %}
|
{% if sakura.dev.showChangelog and stats %}
|
||||||
<script type="text/javascript" src="https://sakura.flash.moe/?get=all&limit=5&variable=true"></script>
|
<script type="text/javascript" src="https://sakura.flash.moe/?get=all&limit=5&variable=true"></script>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% set alerts = alerts|batch(10) %}
|
{% set alerts = user.notifications(0, false)|batch(10) %}
|
||||||
|
|
||||||
{% set paginationPages = alerts %}
|
{% set paginationPages = alerts %}
|
||||||
{% set paginationUrl %}{{ urls.format('SETTING_MODE', ['notifications', 'history']) }}{% endset %}
|
{% set paginationUrl %}{{ urls.format('SETTING_MODE', ['notifications', 'history']) }}{% endset %}
|
||||||
|
@ -14,25 +14,25 @@
|
||||||
{% if alerts %}
|
{% if alerts %}
|
||||||
<div class="notification-history">
|
<div class="notification-history">
|
||||||
{% for alert in alerts[get.page|default(1) - 1] %}
|
{% for alert in alerts[get.page|default(1) - 1] %}
|
||||||
<a id="notif-hist-{{ alert.alert_id }}" class="clean {% if alert.alert_read %}read{% endif %}"{% if alert.alert_link %} href="{{ alert.alert_link }}"{% endif %}>
|
<a id="notif-hist-{{ alert.id }}" class="clean {% if alert.read %}read{% endif %}"{% if alert.link %} href="{{ alert.link }}"{% endif %}>
|
||||||
<div class="notif-hist-icon">
|
<div class="notif-hist-icon">
|
||||||
{% if 'FONT:' in alert.alert_img %}
|
{% if 'FONT:' in alert.image %}
|
||||||
<div class="font-icon fa {{ alert.alert_img|replace({'FONT:': ''}) }} fa-4x"></div>
|
<div class="font-icon fa {{ alert.image|replace({'FONT:': ''}) }} fa-4x"></div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<img src="{{ alert.alert_img }}" alt="Notification" />
|
<img src="{{ alert.image }}" alt="Notification" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="notif-hist-content">
|
<div class="notif-hist-content">
|
||||||
<div class="notif-hist-inside">
|
<div class="notif-hist-inside">
|
||||||
<div class="notif-hist-title">
|
<div class="notif-hist-title">
|
||||||
{{ alert.alert_title }}
|
{{ alert.title }}
|
||||||
</div>
|
</div>
|
||||||
<div class="notif-hist-text">
|
<div class="notif-hist-text">
|
||||||
{{ alert.alert_text }}
|
{{ alert.title }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="notif-hist-time">
|
<div class="notif-hist-time">
|
||||||
<time>{{ alert.alert_timestamp|date(sakura.dateFormat) }}</time>
|
<time>{{ alert.time|date(sakura.dateFormat) }}</time>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="clear"></div>
|
<div class="clear"></div>
|
||||||
|
|
Reference in a new issue