Skip to content

Commit

Permalink
Merge pull request #9617 from cl8n/news-announcements
Browse files Browse the repository at this point in the history
Add news announcement carousel to dashboard
  • Loading branch information
notbakaneko authored Oct 7, 2024
2 parents 659347f + 1ae898e commit 702d218
Show file tree
Hide file tree
Showing 13 changed files with 474 additions and 0 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ CLIENT_CHECK_VERSION=false
# OSU_URL_LAZER_OTHER='https://github.com/ppy/osu/#running-osu'
# OSU_URL_LAZER_WINDOWS_X64='https://github.com/ppy/osu/releases/latest/download/install.exe'
# OSU_URL_LAZER_INFO=
# OSU_URL_MENU_CONTENT_JSON=https://assets.ppy.sh/menu-content.json
# OSU_URL_USER_RESTRICTION=/wiki/Help_centre/Account_restrictions

# USER_COUNTRY_CHANGE_MAX_MIXED_MONTHS=2
Expand Down
4 changes: 4 additions & 0 deletions app/Http/Controllers/HomeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@

use App;
use App\Libraries\CurrentStats;
use App\Libraries\MenuContent;
use App\Libraries\Search\AllSearch;
use App\Libraries\Search\QuickSearch;
use App\Models\BeatmapDownload;
use App\Models\Beatmapset;
use App\Models\Forum\Post;
use App\Models\NewsPost;
use App\Models\UserDonation;
use App\Transformers\MenuImageTransformer;
use Auth;
use Jenssegers\Agent\Agent;
use Request;
Expand Down Expand Up @@ -98,10 +100,12 @@ public function index()
$news = NewsPost::default()->limit($newsLimit)->get();

if (Auth::check()) {
$menuImages = json_collection(MenuContent::activeImages(), new MenuImageTransformer());
$newBeatmapsets = Beatmapset::latestRanked();
$popularBeatmapsets = Beatmapset::popular()->get();

return ext_view('home.user', compact(
'menuImages',
'newBeatmapsets',
'news',
'popularBeatmapsets'
Expand Down
67 changes: 67 additions & 0 deletions app/Libraries/MenuContent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

declare(strict_types=1);

namespace App\Libraries;

use Carbon\Carbon;
use Exception;
use GuzzleHttp\Client;

class MenuContent
{
/**
* Get all active menu content images.
*
* @return array<string, mixed>[]
*/
public static function activeImages(): array
{
return cache_remember_mutexed('menu-content-active-images', 60, [], function () {
$images = self::parse(self::fetch());
$now = Carbon::now();

return array_values(array_filter($images, fn ($image) => (
($image['started_at']?->lessThanOrEqualTo($now) ?? true)
&& ($image['ended_at']?->greaterThan($now) ?? true)
)));
});
}

private static function fetch(): array
{
$response = (new Client())
->get(osu_url('menu_content'))
->getBody()
->getContents();

return json_decode($response, true);
}

private static function parse(array $data): array
{
if (!is_array($data['images'] ?? null)) {
throw new Exception('Invalid "images" key in menu-content response');
}

$parsedImages = [];

foreach ($data['images'] as $image) {
if (!is_string($image['image']) || !is_string($image['url'])) {
throw new Exception('Invalid "image" or "url" key in menu-content image');
}

$parsedImages[] = [
'ended_at' => parse_time_to_carbon($image['expires']),
'image_url' => $image['image'],
'started_at' => parse_time_to_carbon($image['begins']),
'url' => $image['url'],
];
}

return $parsedImages;
}
}
21 changes: 21 additions & 0 deletions app/Transformers/MenuImageTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

declare(strict_types=1);

namespace App\Transformers;

class MenuImageTransformer extends TransformerAbstract
{
public function transform(array $menuImage): array
{
return [
'ended_at' => json_time($menuImage['ended_at']),
'image_url' => $menuImage['image_url'],
'started_at' => json_time($menuImage['started_at']),
'url' => $menuImage['url'],
];
}
}
1 change: 1 addition & 0 deletions config/osu.php
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@
'lazer_dl.windows_x64' => presence(env('OSU_URL_LAZER_WINDOWS_X64')) ?? 'https://github.com/ppy/osu/releases/latest/download/install.exe',
'lazer_dl_other' => presence(env('OSU_URL_LAZER_OTHER')) ?? 'https://github.com/ppy/osu/#running-osu',
'lazer_info' => presence(env('OSU_URL_LAZER_INFO')),
'menu_content' => presence(env('OSU_URL_MENU_CONTENT_JSON')) ?? 'https://assets.ppy.sh/menu-content.json',
'osx' => 'https://osx.ppy.sh',
'server_status' => 'https://status.ppy.sh',
'smilies' => '/forum/images/smilies',
Expand Down
2 changes: 2 additions & 0 deletions resources/css/bem-index.less
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@
@import "bem/logo";
@import "bem/love-beatmap-dialog";
@import "bem/medals-group";
@import "bem/menu-image";
@import "bem/menu-images";
@import "bem/message-length-counter";
@import "bem/mobile-menu";
@import "bem/mobile-menu-tab";
Expand Down
16 changes: 16 additions & 0 deletions resources/css/bem/menu-image.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

.menu-image {
--index: 0;
width: 100%;
height: 100%;
left: calc(100% * var(--index));
position: absolute;

&__image {
object-fit: contain;
width: 100%;
height: 100%;
}
}
106 changes: 106 additions & 0 deletions resources/css/bem/menu-images.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

.menu-images {
--arrow-opacity: 0;
--container-height: 90px;
--indicators-opacity: 1;

margin-top: 20px;
overflow-x: hidden;
position: relative;

&:hover {
--arrow-opacity: 1;
}

&--placeholder {
--indicators-opacity: 0;
}

&__arrow {
.reset-input();
.fade-element(@hover-transition-duration);
height: var(--container-height);
padding: 10px;
position: absolute;
top: 0;
opacity: var(--arrow-opacity);

&:hover {
color: @osu-colour-l1;
}

&--left {
--icon: @fa-var-chevron-left;
left: 0;
}

&--right {
--icon: @fa-var-chevron-right;
right: 0;
}

&::before {
.fas();
.default-text-shadow();
content: var(--icon);
}
}

&__container {
.center-content();
display: flex;
height: var(--container-height);
transform: translateX(calc(-100% * var(--index, 0)));

&--transition {
transition: transform 300ms ease-in-out;
}
}

&__indicator {
.reset-input();
align-items: center;
display: flex;

width: 30px;
height: 6px;

--content-height: 2px;
--content-opacity: 0.5;

&::before {
content: "";

background: @osu-colour-h1;
border-radius: 10000px;
opacity: var(--content-opacity);

transition: 100ms ease-out;
transition-property: height, opacity;

width: 100%;
height: var(--content-height);
}

&:hover {
--content-height: 100%;
}

&--active {
--content-height: 100%;
--content-opacity: 1;
}
}

&__indicators {
align-items: center;
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: center;
margin-top: 10px;
opacity: var(--indicators-opacity);
}
}
24 changes: 24 additions & 0 deletions resources/js/components/menu-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

import MenuImageJson from 'interfaces/menu-image-json';
import * as React from 'react';

const bn = 'menu-image';

interface Props {
image: MenuImageJson;
index?: number;
}

export default function MenuImage({ image, index }: Props) {
return (
<a
className={bn}
href={image.url}
style={{ '--index': index } as React.CSSProperties}
>
<img className={`${bn}__image`} src={image.image_url} />
</a>
);
}
Loading

0 comments on commit 702d218

Please sign in to comment.