2019-01-24 17:43:03 +09:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
2018-04-13 18:19:50 +09:00
using osu.Game.Online.Chat ;
using System ;
using System.Linq ;
using osu.Framework.Allocation ;
using osu.Framework.Graphics.Sprites ;
using System.Collections.Generic ;
2018-12-26 18:05:12 +09:00
using osu.Framework.Graphics ;
2018-07-23 22:06:40 +02:00
using osu.Framework.Logging ;
2018-04-13 18:19:50 +09:00
using osu.Game.Overlays ;
using osu.Game.Overlays.Notifications ;
2019-04-05 14:15:36 +09:00
using osu.Game.Users ;
2018-04-13 18:19:50 +09:00
namespace osu.Game.Graphics.Containers
{
public class LinkFlowContainer : OsuTextFlowContainer
{
public LinkFlowContainer ( Action < SpriteText > defaultCreationParameters = null )
: base ( defaultCreationParameters )
{
}
private OsuGame game ;
2018-04-14 13:31:03 +02:00
private ChannelManager channelManager ;
2018-04-13 18:19:50 +09:00
private Action showNotImplementedError ;
[BackgroundDependencyLoader(true)]
2018-11-18 16:10:36 +03:00
private void load ( OsuGame game , NotificationOverlay notifications , ChannelManager channelManager )
2018-04-13 18:19:50 +09:00
{
// will be null in tests
this . game = game ;
2018-04-14 13:31:03 +02:00
this . channelManager = channelManager ;
2018-10-22 23:57:37 +03:00
2018-04-13 18:19:50 +09:00
showNotImplementedError = ( ) = > notifications ? . Post ( new SimpleNotification
{
Text = @"This link type is not yet supported!" ,
2019-04-02 19:55:24 +09:00
Icon = FontAwesome . Solid . LifeRing ,
2018-04-13 18:19:50 +09:00
} ) ;
}
public void AddLinks ( string text , List < Link > links )
{
if ( string . IsNullOrEmpty ( text ) | | links = = null )
return ;
if ( links . Count = = 0 )
{
AddText ( text ) ;
return ;
}
int previousLinkEnd = 0 ;
2019-04-01 12:16:05 +09:00
2018-04-13 18:19:50 +09:00
foreach ( var link in links )
{
AddText ( text . Substring ( previousLinkEnd , link . Index - previousLinkEnd ) ) ;
AddLink ( text . Substring ( link . Index , link . Length ) , link . Url , link . Action , link . Argument ) ;
previousLinkEnd = link . Index + link . Length ;
}
AddText ( text . Substring ( previousLinkEnd ) ) ;
}
2019-01-22 14:22:38 +09:00
public IEnumerable < Drawable > AddLink ( string text , string url , LinkAction linkType = LinkAction . External , string linkArgument = null , string tooltipText = null , Action < SpriteText > creationParameters = null )
2018-12-26 18:05:12 +09:00
= > createLink ( AddText ( text , creationParameters ) , text , url , linkType , linkArgument , tooltipText ) ;
2019-01-22 14:22:38 +09:00
public IEnumerable < Drawable > AddLink ( string text , Action action , string tooltipText = null , Action < SpriteText > creationParameters = null )
2018-12-26 18:05:12 +09:00
= > createLink ( AddText ( text , creationParameters ) , text , tooltipText : tooltipText , action : action ) ;
2019-01-22 14:22:38 +09:00
public IEnumerable < Drawable > AddLink ( IEnumerable < SpriteText > text , string url , LinkAction linkType = LinkAction . External , string linkArgument = null , string tooltipText = null )
2018-12-26 18:05:12 +09:00
{
foreach ( var t in text )
AddArbitraryDrawable ( t ) ;
2019-01-22 14:22:38 +09:00
return createLink ( text , null , url , linkType , linkArgument , tooltipText ) ;
2018-12-26 18:05:12 +09:00
}
2019-04-05 14:15:36 +09:00
public IEnumerable < Drawable > AddUserLink ( User user , Action < SpriteText > creationParameters = null )
= > createLink ( AddText ( user . Username , creationParameters ) , user . Username , null , LinkAction . OpenUserProfile , user . Id . ToString ( ) , "View profile" ) ;
2019-01-22 14:22:38 +09:00
private IEnumerable < Drawable > createLink ( IEnumerable < Drawable > drawables , string text , string url = null , LinkAction linkType = LinkAction . External , string linkArgument = null , string tooltipText = null , Action action = null )
2018-04-13 18:19:50 +09:00
{
2018-12-26 18:05:12 +09:00
AddInternal ( new DrawableLinkCompiler ( drawables . OfType < SpriteText > ( ) . ToList ( ) )
2018-04-13 18:19:50 +09:00
{
2019-01-08 18:58:44 +09:00
RelativeSizeAxes = Axes . Both ,
2018-04-13 18:19:50 +09:00
TooltipText = tooltipText ? ? ( url ! = text ? url : string . Empty ) ,
2018-12-26 18:05:12 +09:00
Action = action ? ? ( ( ) = >
2018-04-13 18:19:50 +09:00
{
switch ( linkType )
{
case LinkAction . OpenBeatmap :
2018-04-18 13:08:53 +09:00
// TODO: proper query params handling
if ( linkArgument ! = null & & int . TryParse ( linkArgument . Contains ( '?' ) ? linkArgument . Split ( '?' ) [ 0 ] : linkArgument , out int beatmapId ) )
game ? . ShowBeatmap ( beatmapId ) ;
2018-04-13 18:19:50 +09:00
break ;
2019-04-01 12:16:05 +09:00
2018-04-13 18:19:50 +09:00
case LinkAction . OpenBeatmapSet :
if ( int . TryParse ( linkArgument , out int setId ) )
game ? . ShowBeatmapSet ( setId ) ;
break ;
2019-04-01 12:16:05 +09:00
2018-04-13 18:19:50 +09:00
case LinkAction . OpenChannel :
2018-04-14 13:31:03 +02:00
try
{
2018-09-14 11:58:23 +09:00
channelManager ? . OpenChannel ( linkArgument ) ;
2018-04-14 13:31:03 +02:00
}
2019-04-25 17:36:17 +09:00
catch ( ChannelNotFoundException )
2018-04-14 13:31:03 +02:00
{
2018-09-14 11:58:23 +09:00
Logger . Log ( $"The requested channel \" { linkArgument } \ " does not exist" ) ;
2018-04-14 13:31:03 +02:00
}
2018-07-24 15:10:55 +02:00
2018-04-13 18:19:50 +09:00
break ;
2019-04-01 12:16:05 +09:00
2018-04-13 18:19:50 +09:00
case LinkAction . OpenEditorTimestamp :
case LinkAction . JoinMultiplayerMatch :
case LinkAction . Spectate :
showNotImplementedError ? . Invoke ( ) ;
break ;
2019-04-01 12:16:05 +09:00
2018-04-13 18:19:50 +09:00
case LinkAction . External :
2018-10-23 23:03:00 +03:00
game ? . OpenUrlExternally ( url ) ;
2018-04-13 18:19:50 +09:00
break ;
2019-04-01 12:16:05 +09:00
2018-04-13 18:19:50 +09:00
case LinkAction . OpenUserProfile :
if ( long . TryParse ( linkArgument , out long userId ) )
game ? . ShowUser ( userId ) ;
break ;
2019-04-01 12:16:05 +09:00
2018-04-13 18:19:50 +09:00
default :
throw new NotImplementedException ( $"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action." ) ;
}
2018-12-26 18:05:12 +09:00
} ) ,
2018-04-13 18:19:50 +09:00
} ) ;
2019-01-22 14:22:38 +09:00
return drawables ;
2018-04-13 18:19:50 +09:00
}
2019-01-08 18:58:44 +09:00
2019-01-10 14:55:36 +09:00
// We want the compilers to always be visible no matter where they are, so RelativeSizeAxes is used.
// However due to https://github.com/ppy/osu-framework/issues/2073, it's possible for the compilers to be relative size in the flow's auto-size axes - an unsupported operation.
// Since the compilers don't display any content and don't affect the layout, it's simplest to exclude them from the flow.
2019-01-08 18:58:44 +09:00
public override IEnumerable < Drawable > FlowingChildren = > base . FlowingChildren . Where ( c = > ! ( c is DrawableLinkCompiler ) ) ;
2018-04-13 18:19:50 +09:00
}
}